library(shiny)
library(dplyr)
library(tidyr)
library(ggplot2)
library(readr)
library(maps)
library(usmap)
library(gridExtra)
library(biscale)
library(cowplot)
library(sf)
library(shinythemes)
# ------------------------
# import data
# ------------------------
Children_TX <-read.csv("CData/Children_TX.csv")
Homes <-read.csv("CData/Homes.csv")
Removals <-read.csv("CData/Removals.csv")
map_data <- read.csv("CData/Shiny_map_data.csv")
states <- map_data("state") %>% filter(region == "texas") %>% filter(order > 13025) %>%
usmap_transform()
Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj = prefer_proj) :
Discarded datum unknown in Proj4 definition
write_csv(states, "ShinyApp/CData/states.csv")
# --------------------------------------------
# CREATING BLANK MAP OF THE TEXAS COUNTIES
# --------------------------------------------
map_data$empty_vec = rep(NA, 254)
plot_usmap(data = map_data, values = "empty_vec", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = "white", na.value="white") +
theme(plot.background = element_rect(color = "gray", fill = "gray"))

# ---------------
# --------------------------------------------
# CREATING MAP OF THE TEXAS DFPS REGIONS
# --------------------------------------------
legend_text = "DFPS Region"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == 2021)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"DReg_Num", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$DReg_Num
data <- cbind(mdata,var1)
data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#f58231","#42d4f4","#911eb4","#fabed4","#007c7c","#aaffc3","#4363d8","#dcbeff","#c50275","#ffe119","#98D640")
labels <- c()
brks <- c(0,1, 2, 3, 4, 5, 6, 7, 8, 9,10,11)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
plot_usmap(data = data, values = "brks", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = c(" 1 Lubbock"," 2 Abilene"," 3 Arlington"," 4 Tyler"," 5 Beaumont"," 6 Houston"," 7 Austin"," 8 San Antonio"," 9 Midland","10 El Paso","11 Edinburg"),
guide = guide_legend(
direction = "vertical",
keyheight = unit(6, units = "mm"),
keywidth = unit(100 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 0,
nrow = 12,
byrow = F,
reverse = F,
label.position = "right"),
na.translate = FALSE) +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=14)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="left")

#library(ragg)
#ragg::agg_png("ragg_5x5.png", width = 5, height = 5, units = "in", res = 300, scaling = 0.5)
#fig01
#dev.off()
# -----------------------------------------------------------------
# Determining the Binned Intervals for the Homes and Removals Data
# -----------------------------------------------------------------
# Building the parts of the dataframe we will work with
mdata <- map_data %>% select("Year", "County",
"Homes_Total_County_per100K",
"Removals_Total_County_per1K", "CBC")
# Only want the data points from counties with DFPS foster care (not CBC foster care)
mdata <- mdata %>% filter(CBC == "DFPS")
mdata$Year<-as.factor(mdata$Year)
new1 <-mdata %>% group_by(County) %>% summarise(MeanHomes = mean(Homes_Total_County_per100K)) %>% select("MeanHomes")
new2 <-mdata %>% group_by(County) %>% summarise(MeanRemovals = mean(Removals_Total_County_per1K)) %>% select("MeanRemovals")
new1$MeanHomes[new1$MeanHomes==0] <- NA
new2$MeanRemovals[new2$MeanRemovals==0] <- NA
# Plot 1
layout(mat = matrix(c(1,2),2,1, byrow=TRUE), height = c(1,8))
par(mar=c(0, 3.1, 1.1, 2.1))
boxplot(new1$MeanHomes, horizontal=TRUE , ylim=c(0,50), xaxt="n" , col=rgb(3/255,149/255,114/255,0.85) , frame=F)
par(mar=c(4, 3.1, 1.1, 2.1))
hist(new1$MeanHomes, breaks=40 , col=rgb(0/255,0/255,124/255,0.85) , border=T , main="" , xlab="Average Number of Homes Per 100K Residents between 2011-2021", xlim=c(0,50))
# Plot 2
layout(mat = matrix(c(1,2),2,1, byrow=TRUE), height = c(1,8))
par(mar=c(0, 3.1, 1.1, 2.1))

boxplot(new2$MeanRemovals, horizontal=TRUE , ylim=c(0,15), xaxt="n" , col=rgb(3/255,149/255,114/255,0.85) , frame=F) + geom_hline(xintercept=10)
Warning: Ignoring unknown parameters: xintercept
NULL
par(mar=c(4, 3.1, 1.1, 2.1))
hist(new2$MeanRemovals, breaks=40 , col=rgb(0/255,0/255,124/255,0.85) , border=T , main="" , xlab="Average Number of Removals Per 1K Children between 2011-2021", xlim=c(0,15))

# Bins for Homes
quantile(new1$MeanHomes,probs = 0.33333,na.rm = TRUE)
33.333%
5.786619
quantile(new1$MeanHomes,probs = 0.66667,na.rm = TRUE)
66.667%
11.22218
# Bins for Removals
quantile(new2$MeanRemovals,probs = 0.33333,na.rm = TRUE)
33.333%
2.935043
quantile(new2$MeanRemovals,probs = 0.66667,na.rm = TRUE)
66.667%
4.824873
# testing out the exclude input in plot_usmap
# also testing adding the outline of the Texas panhandle
counties <- map_data("county") %>% filter(region == "texas") %>% filter(subregion==c("travis")) %>%
usmap_transform()
Warning in showSRID(uprojargs, format = "PROJ", multiline = "NO", prefer_proj = prefer_proj) :
Discarded datum unknown in Proj4 definition
map_data_year <- filter(map_data, Year == 2021)
fips_list = (map_data_year$fips[map_data_year$CBC=="CBC"])
p <- plot_usmap(data = map_data_year, values = "empty_vec", include = c("TX"), exclude = fips_list, color = "black")
plot_usmap(data = map_data_year, values = "empty_vec", include = c("TX"), exclude = fips_list, color = "black") +
theme_map() +
scale_fill_manual(
values = "white", na.value="white") +
theme(plot.background = element_rect(color = "gray", fill = "gray")) +
geom_path(data = states,
aes(x = long.1,
y = lat.1),
color = "red") +
geom_path(data = counties,
aes(x = long.1,
y = lat.1),
color = "blue")

NA
NA
# -------------------------
# Plotting Functions
# -------------------------
create_homes_removals_plot <- function(map_data, year, states) {
color_map = c("#da4f58","#eda8a9","#e8e7e6",
"#a44c55","#b09ca5","#a4d5e1",
"#5a3f49","#5b7d8f","#43aac0")
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
fips_list = (map_data_year$fips[map_data_year$CBC=="CBC"])
# -----------------------------------------
# The breaks:
x_brk_points = c(3, 5) # removals
y_brk_points = c(6, 11) # homes
# -----------------------------------------
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat","CBC")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
var2 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1,var2)
x = as.numeric(unlist(data[8]))
y = as.numeric(unlist(data[9]))
# create 3 buckets for variable 1
quantiles_x <- quantile(x,
probs = c(0,ecdf(x)(x_brk_points[1]),
ecdf(x)(x_brk_points[2]),1), na.rm = TRUE)
# create 3 buckets for variable 2
quantiles_y <- quantile(y,
probs = c(0,ecdf(y)(y_brk_points[1]),
ecdf(y)(y_brk_points[2]),1), na.rm = TRUE)
# create color scale that encodes two variables
bivariate_color_scale <- tibble(
"3 - 3" = color_map[1], # high X, high Y
"2 - 3" = color_map[2],
"1 - 3" = color_map[3], # low X, high Y
"3 - 2" = color_map[4],
"2 - 2" = color_map[5], # medium X, medium Y
"1 - 2" = color_map[6],
"3 - 1" = color_map[7], # high X, low Y
"2 - 1" = color_map[8],
"1 - 1" = color_map[9] # low X, low Y
) %>%
gather("group", "fill")
# cut into groups defined above and join fill
bar <- data %>%
mutate(
x_quantiles = cut(
x,
breaks = quantiles_x,
include.lowest = TRUE
),
y_quantiles = cut(
y,
breaks = quantiles_y,
include.lowest = TRUE
),
group = paste(
as.numeric(x_quantiles), "-",
as.numeric(y_quantiles)
)
) %>%
# we now join the actual hex values per "group"
# so each county has a hex value based on x and y
left_join(bivariate_color_scale, by = "group")
foo = bar %>% select(fips,fill)
colours = color_map
## ----------------------------------------------------------------
bivar_plot <- plot_usmap(data = foo, values = "fill", include = c("TX"), exclude = fips_list, color = "black", ) +
scale_fill_manual(
values = colours,
breaks = colours,
drop = FALSE, na.value = "white") + theme(legend.position = "none") +
theme(plot.background = element_rect(color = "white", fill = "white")) +
geom_path(data = states,
aes(x = long.1,
y = lat.1),
color = "black")
return(bivar_plot)
} # END OF FUNCTION # 1
create_homes_plot_simple <- function(map_data, year, states) {
legend_text = "FAD Homes per 100K residents"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
fips_list = (map_data_year$fips[map_data_year$CBC=="CBC"])
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat", "CBC")
# create dataframe we will work with to plot
var1 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1)
data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
#colours = c("#a9a9a9","#f55702","#f07d03","#25999b","#007c7f","#015c5d")
colours = c("#a9a9a9","#3f2e84","#1032a1","#25999b","#007c7f","#015c5d")
labels <- c()
brks <- c(0,10, 25, 50, 75, 100, 125)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
labels_scale = append(labels_scale, "ZERO")
# --------------------------------
univar_plot <-plot_usmap(data = data, values = "brks", include = c("TX"), exclude = fips_list, color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = labels_scale,
guide = guide_legend(
direction = "horizontal",
keyheight = unit(6, units = "mm"),
keywidth = unit(100 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 1,
byrow = T,
reverse = F,
label.position = "bottom"),
na.translate = TRUE, na.value = "yellow") +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=14)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="top") +
geom_path(data = states,
aes(x = long.1,
y = lat.1),
color = "black")
return(univar_plot)
} # END OF FUNCTION # 2
create_removals_plot_simple <- function(map_data, year) {
legend_text = "Removals per 1K children"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
data <- cbind(mdata,var1)
data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
#colours = c("#a9a9a9","#1032a1","#3f2e84","#6e2a67","#9c2449","#cc202a")
colours = c("#a9a9a9","#f07d03","#f55702","#cc202a","#9c2449", "#6e2a67")
labels <- c()
brks <- c(0,5, 10, 15, 20, 30, 50)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
labels_scale = append(labels_scale, "ZERO")
# --------------------------------
univar_plot <-plot_usmap(data = data, values = "brks", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = labels_scale,
guide = guide_legend(
direction = "horizontal",
keyheight = unit(6, units = "mm"),
keywidth = unit(100 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 1,
byrow = T,
reverse = F,
label.position = "bottom"),
na.translate = TRUE, na.value = "yellow") +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=14)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="top")
return(univar_plot)
} # END OF FUNCTION # 3
# extract dataframe from bivariate map
extract_dataframe <- function(map_data, year) {
color_map = c("#da4f58","#eda8a9","#e8e7e6",
"#a44c55","#b09ca5","#a4d5e1",
"#5a3f49","#5b7d8f","#43aac0")
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# -----------------------------------------
# The breaks:
x_brk_points = c(3, 5) # removals
y_brk_points = c(6, 11) # homes
# -----------------------------------------
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"DFPS_Region", "fips", "lon", "lat","CBC")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
var2 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1,var2)
x = as.numeric(unlist(data[8]))
y = as.numeric(unlist(data[9]))
# create 3 buckets for variable 1
quantiles_x <- quantile(x,
probs = c(0,ecdf(x)(x_brk_points[1]),
ecdf(x)(x_brk_points[2]),1), na.rm = TRUE)
# create 3 buckets for variable 2
quantiles_y <- quantile(y,
probs = c(0,ecdf(y)(y_brk_points[1]),
ecdf(y)(y_brk_points[2]),1), na.rm = TRUE)
# create color scale that encodes two variables
bivariate_color_scale <- tibble(
"3 - 3" = color_map[1], # high X, high Y
"2 - 3" = color_map[2],
"1 - 3" = color_map[3], # low X, high Y
"3 - 2" = color_map[4],
"2 - 2" = color_map[5], # medium X, medium Y
"1 - 2" = color_map[6],
"3 - 1" = color_map[7], # high X, low Y
"2 - 1" = color_map[8],
"1 - 1" = color_map[9] # low X, low Y
) %>%
gather("group", "fill")
# cut into groups defined above and join fill
bar <- data %>%
mutate(
x_quantiles = cut(
x,
breaks = quantiles_x,
include.lowest = TRUE
),
y_quantiles = cut(
y,
breaks = quantiles_y,
include.lowest = TRUE
),
group = paste(
as.numeric(x_quantiles), "-",
as.numeric(y_quantiles)
)
) %>%
# we now join the actual hex values per "group"
# so each county has a hex value based on x and y
left_join(bivariate_color_scale, by = "group")
foo = bar %>% select(fips,fill)
colours = color_map
# --------------------------------
return(bar)
} # END OF FUNCTION # 4
# extract dataframe from univariate removals map
extract_dataframe2 <- function(map_data, year) {
legend_text = "Removals per 1K children"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
data <- cbind(mdata,var1)
data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#a9a9a9","#eac259","#f39f62","#f67300","#e52835","#810301")
labels <- c()
brks <- c(0,5, 10, 15, 20, 30, 50)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
return(data)
} # END OF FUNCTION # 5
# -----------------------------
# Homes between 2011-2018
# -----------------------------
Homes %>% filter(Year %in% c(2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018)) %>% group_by(Year) %>% summarise(Total = sum(Count))
Homes %>% filter(Year %in% c(2011, 2012, 2013, 2014, 2015, 2016)) %>% group_by(Year, Type) %>% summarise(Total = sum(Count)) %>%
ggplot(aes(x = Year, y = Total, fill = Type)) +
geom_bar(stat = 'identity') +
ggtitle("") +
scale_x_continuous(name="Year", limits=c(2010.5, 2016.5), breaks = c(2011,2012,2013,2014,2015,2016)) +
theme(plot.title = element_text(hjust = 0.5)) +
theme(axis.text.x = element_text(color="black", size=12, angle=0)) +
theme(axis.text.y = element_text(color="black", size=14, angle=0)) +
theme(axis.title = element_text(size = 16)) +
theme(legend.text = element_text(size = 14)) +
theme(legend.title = element_text(size = 14)) +
theme(plot.title = element_text(size = 14)) +
scale_fill_manual(name = "Home Type", values = c("#636363","#aeaeae","black"))
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.

Homes_Region <- Homes %>% filter(CBC == "DFPS") %>% group_by(Region, Year) %>% summarise(Total_Homes = sum(Count))
`summarise()` has grouped output by 'Region'. You can override using the `.groups` argument.
Population_Region <- Children_TX %>% group_by(Region, Year) %>% summarise(Total_Pop = sum(Total_Population))
`summarise()` has grouped output by 'Region'. You can override using the `.groups` argument.
Homes_toplot <- Homes_Region %>% merge(Population_Region,by=c("Region","Year"))
Homes_toplot$HomesPer100K = (Homes_toplot$Total_Homes/Homes_toplot$Total_Pop)*100000
colours = c("#42d4f4","#c50275")
#ylab_rot <- gsub(" ", "\n", "FAD Homes Per 100K Residents")
ylab_test <-("FAD Homes\nper 100K\nresidents")
Homes_toplot %>% filter(Region %in% c("2-Abilene","9-Midland")) %>%
ggplot( aes(x=Year, y=HomesPer100K, group=Region, color = Region))+
geom_line(size=3.5, alpha=0.8) +
scale_colour_manual(name="DFPS Region",
values = colours,labels = c(" 2-Abilene"," 9-Midland")) +
scale_x_continuous(breaks = c(2011,2013,2015,2017,2019,2021)) + ylab(ylab_test) + theme(axis.title.y=element_text(angle=0,vjust=0.5)) +
theme(plot.title = element_text(hjust = 0.5)) +
theme(axis.text.x = element_text(color="black", size=12, angle=0)) +
theme(axis.text.y = element_text(color="black", size=14, angle=0)) +
theme(axis.title = element_text(size = 16)) +
theme(legend.text = element_text(size = 14)) +
theme(legend.title = element_text(size = 14)) +
theme(plot.title = element_text(size = 14))

Homes_Year <- Homes %>% filter(CBC == "DFPS") %>% group_by(Year, Type) %>% summarise(Total_Homes = sum(Count))
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
Population_Year <- map_data %>% filter(CBC == "DFPS") %>% group_by(Year) %>% summarise(Total_Pop = sum(Total_Population))
Homes_Population_Year <- Homes_Year %>% merge(Population_Year,by=c("Year"))
Homes_Population_Year$HomesPer100K = (Homes_Population_Year$Total_Homes/Homes_Population_Year$Total_Pop)*100000
ylab_test <-("FAD Homes\nper 100K\nresidents")
Homes_Population_Year %>% filter(Year %in% c(2011,2013,2015,2017,2019,2021)) %>% group_by(Year) %>% summarise(Total = sum(HomesPer100K))
Homes_Population_Year %>% filter(Year %in% c(2011,2013,2015,2017,2019,2021)) %>% ggplot(aes(x = Year, y = HomesPer100K, fill=Type)) +
geom_bar(stat = 'identity') +
ggtitle("") +
theme(plot.title = element_text(hjust = 0.5)) +
theme(axis.text.x = element_text(color="black", size=12, angle=0)) +
theme(axis.text.y = element_text(color="black", size=12, angle=0)) +
theme(axis.title = element_text(size = 16)) +
theme(legend.text = element_text(size = 14)) +
theme(legend.title = element_text(size = 14)) +
theme(plot.title = element_text(size = 14)) +
scale_x_continuous(breaks = c(2011,2013,2015,2017,2019,2021)) + ylab(ylab_test) + theme(axis.title.y=element_text(angle=0,vjust=0.55,hjust=0.50)) +
scale_fill_manual(name = "Home Type", values = c("#636363","#aeaeae","black"))

# -----------------------------
# Homes Texas Maps
# -----------------------------
# -----------------
# 2011 bar chart
# -----------------
map_data_2011 <- map_data %>% filter((Year == "2011") & (CBC == "DFPS")) %>% filter(Homes_Total_County==0)
sum(map_data_2011$Homes_Total_County==0)
[1] 53
map_data_2011 <- within(map_data_2011,
Region<- factor(Region,
levels=names(sort(table(Region),
decreasing=FALSE))))
ggplot(map_data_2011, aes(y = Region)) +
geom_bar(fill="black") + theme(axis.text.x = element_text(color="black", size=9, angle=0)) + labs(y = "Region", x = "County Count")

# -----------------
# 2015 bar chart
# -----------------
map_data_2015 <- map_data%>% filter((Year == "2015") & (CBC == "DFPS")) %>% filter(Homes_Total_County==0)
sum(map_data_2015$Homes_Total_County==0)
[1] 97
map_data_2015 <- within(map_data_2015,
Region<- factor(Region,
levels=names(sort(table(Region),
decreasing=FALSE))))
ggplot(map_data_2015, aes(y = Region)) +
geom_bar(fill="black") + theme(axis.text.x = element_text(color="black", size=9, angle=0)) + labs(y = "DReg_Num", x = "County Count")

# -----------------
# maps figure (2 Years)
# -----------------
fig1 = create_homes_plot_simple(map_data, 2011, states) +
theme(legend.position="none")
fig2 = create_homes_plot_simple(map_data, 2012, states) +
theme(legend.position="none")
fig3 = create_homes_plot_simple(map_data, 2013, states) +
theme(legend.position="none")
fig4 = create_homes_plot_simple(map_data, 2014, states) +
theme(legend.position="none")
fig5 = create_homes_plot_simple(map_data, 2015, states) +
theme(legend.position="none")
fig6 = create_homes_plot_simple(map_data, 2016, states) +
theme(legend.position="none")
fig7 = create_homes_plot_simple(map_data, 2017, states) +
theme(legend.position="none")
fig8 = create_homes_plot_simple(map_data, 2018, states) +
theme(legend.position="none")
fig9 = create_homes_plot_simple(map_data, 2019, states) +
theme(legend.position="none")
fig10 = create_homes_plot_simple(map_data, 2020, states) +
theme(legend.position="none")
fig11 = create_homes_plot_simple(map_data, 2021, states) +
theme(legend.position="none")
grid.arrange(fig1+ggtitle("2011")+theme(plot.title = element_text(hjust = 0.35)),
fig11+ggtitle("2021")+theme(plot.title = element_text(hjust = 0.35)),
nrow = 1)

# -----------------
# maps figures (2 Years - another version)
# -----------------
library(ggpubr)
fig0 = create_homes_plot_simple(map_data, 2021, states)
fig0 <- fig0 + theme(text=element_text(size=12), legend.text=element_text(size=10))
leg <- get_legend(fig0)
legh <- as_ggplot(leg) # converting to ggplot
legh

homes_2011 <- fig1+ggtitle("2011")+theme(plot.title = element_text(hjust = 0.35))
homes_2021 <- fig11+ggtitle("2021")+theme(plot.title = element_text(hjust = 0.35))
library(patchwork)
layout <- "
A#
BC
BC
"
legh + homes_2011 + homes_2021 + plot_layout(design = layout)

fig1t <- fig1+ggtitle("2011")+theme(plot.title = element_text(hjust = 0.35))
fig2t <- fig2+ggtitle("2012")+theme(plot.title = element_text(hjust = 0.35))
fig3t <- fig3+ggtitle("2013")+theme(plot.title = element_text(hjust = 0.35))
fig4t <- fig4+ggtitle("2014")+theme(plot.title = element_text(hjust = 0.35))
fig5t <- fig5+ggtitle("2015")+theme(plot.title = element_text(hjust = 0.35))
fig6t <- fig6+ggtitle("2016")+theme(plot.title = element_text(hjust = 0.35))
fig7t <- fig7+ggtitle("2017")+theme(plot.title = element_text(hjust = 0.35))
fig8t <- fig8+ggtitle("2018")+theme(plot.title = element_text(hjust = 0.35))
fig9t <- fig9+ggtitle("2019")+theme(plot.title = element_text(hjust = 0.35))
fig10t <- fig10+ggtitle("2020")+theme(plot.title = element_text(hjust = 0.35))
fig11t <- fig11+ggtitle("2021")+theme(plot.title = element_text(hjust = 0.35))
#library(patchwork)
#layout <- "
#ABC
#"
#fig1t + fig3t + fig5t + plot_layout(design = layout)
#fig7t + fig9t + fig11t + plot_layout(design = layout)
grid.arrange(fig1t,fig3t,fig5t,
nrow = 1)

grid.arrange(fig7t, fig9t, fig11t,
nrow = 1)

# -----------------------------
# Removals between 2011-2018
# -----------------------------
Removals %>% group_by(Year) %>% summarise(Total = sum(Removals))
Removals %>% filter(Year %in% c(2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021)) %>% group_by(Year, Removal.Stage) %>% summarise(Total = sum(Removals)) %>% ggplot(aes(x = Year, y = Total, fill = Removal.Stage)) +
geom_bar(stat = 'identity') +
theme(axis.text.x = element_text(color="black", size=12, angle=30)) +
theme(axis.text.y = element_text(color="black", size=12, angle=0)) +
theme(axis.title = element_text(size = 16)) +
theme(legend.text = element_text(size = 14)) +
theme(legend.title = element_text(size = 14)) +
theme(plot.title = element_text(size = 14)) +
ggtitle("") +
scale_x_continuous(name="Year", limits=c(2010.5, 2021.5), breaks = c(2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021)) +
scale_fill_manual(name = "Removal Stage", values = c("#058abd","#1c3152"))
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.

Removals_Year <- Removals %>% group_by(Year, Removal.Stage) %>% summarise(Total_Removals = sum(Removals))
`summarise()` has grouped output by 'Year'. You can override using the `.groups` argument.
Child_Population_Year <- map_data %>% group_by(Year) %>% summarise(Child_Pop = sum(Child_Population))
Removals_Population_Year <- Removals_Year %>% merge(Child_Population_Year,by=c("Year"))
Removals_Population_Year$RemovalsPer1K = (Removals_Population_Year$Total_Removals/Child_Population_Year$Child_Pop)*1000
ylab_test <-("Removals\n per 1K \nchildren")
Removals_Population_Year %>% filter(Year %in% c(2011,2013,2015,2017,2019,2021)) %>% group_by(Year) %>% summarise(Total = sum(RemovalsPer1K)) %>% summarise(Mean = mean(Total))
Removals_Population_Year %>% filter(Year %in% c(2011,2013,2015,2017,2019,2021)) %>% ggplot(aes(x = Year, y = RemovalsPer1K, fill=Removal.Stage)) +
geom_bar(stat = 'identity') +
ggtitle("") +
theme(plot.title = element_text(hjust = 0.5)) +
theme(axis.text.x = element_text(color="black", size=12, angle=0)) +
theme(axis.text.y = element_text(color="black", size=14, angle=0)) +
theme(axis.title = element_text(size = 16)) +
theme(legend.text = element_text(size = 14)) +
theme(legend.title = element_text(size = 14)) +
theme(plot.title = element_text(size = 14)) +
scale_x_continuous(breaks = c(2011,2013,2015,2017,2019,2021)) + ylab(ylab_test) + theme(axis.title.y=element_text(angle=0,vjust=0.50)) + ylim(0,3.01) +
scale_fill_manual(name = "Removal Stage", values = c("#55565B","black"))

# -----------------------------
# Removals Texas Maps
# -----------------------------
# -----------------
# 2018 bar chart
# -----------------
removals_data_2021 <- extract_dataframe2(map_data, 2021)
removals_data_2021_high <- filter(removals_data_2021 , brks!="5") %>% select("Year", "County", "Region","brks")
removals_data_2021_high <- within(removals_data_2021_high,
Region<- factor(Region,
levels=names(sort(table(Region),
decreasing=FALSE))))
ggplot(removals_data_2021_high, aes(y = Region)) +
geom_bar(fill="black") + theme(axis.text.x = element_text(color="black", size=9, angle=0)) + labs(y = "Region", x = "County Count")

# -----------------
# maps figure (2 Years)
# -----------------
fig3 = create_removals_plot_simple(map_data, 2011) +
theme(legend.position="none")
fig4 = create_removals_plot_simple(map_data, 2021) +
theme(legend.position="none")
grid.arrange(fig3+ggtitle("2011")+theme(plot.title = element_text(hjust = 0.35)),
fig4+ggtitle("2021")+theme(plot.title = element_text(hjust = 0.35)),
nrow = 1)

# -----------------
# maps figures (2 Years - another version)
# -----------------
library(ggpubr)
fig = create_removals_plot_simple(map_data, 2021)
fig <- fig + theme(text=element_text(size=12), legend.text=element_text(size=10))
leg <- get_legend(fig)
legh <- as_ggplot(leg)
legh

removals_2011 <- fig3+ggtitle("2011")+theme(plot.title = element_text(hjust = 0.41))
removals_2021 <- fig4+ggtitle("2021")+theme(plot.title = element_text(hjust = 0.41))
library(patchwork)
layout <- "
A#
BC
BC
"
legh + removals_2011 + removals_2021 + plot_layout(design = layout)

# ----------------------------------------------------
# Map Functions for Texas Maps with binned intervals
# ----------------------------------------------------
# Map Function with 3 Breaks
create_homes_plot_simple_3brks <- function(map_data, year, states) {
legend_text = "FAD Homes per 100K residents"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
fips_list = (map_data_year$fips[map_data_year$CBC=="CBC"])
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Homes_Total_County_per100K
data <- cbind(mdata,var1)
#data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#43aabf","#a4d5e1","#969696")
#colours = c("#4d4d4d","#818181","#c6c6c6")
labels <- c()
brks <- c(0,6,11,50)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
univar_plot <-plot_usmap(data = data, values = "brks", include = c("TX"), exclude = fips_list, color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = labels_scale,
guide = guide_legend(
direction = "horizontal",
keyheight = unit(6, units = "mm"),
keywidth = unit(65 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 1,
byrow = T,
reverse = F,
label.position = "bottom"),
na.translate = FALSE) +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=12)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="top") + theme(text=element_text(size=12)) +
geom_path(data = states,
aes(x = long.1,
y = lat.1),
color = "black")
return(univar_plot)
} # END OF FUNCTION # 2 updated
create_removals_plot_simple_3brks <- function(map_data, year) {
legend_text = "Removals per 1K children"
# Filter for Chosen Year
map_data_year <- filter(map_data, Year == year)
# Building the parts of the dataframe we will work with
mdata <- map_data_year %>% select("Year", "County",
"Region", "fips", "lon", "lat")
# create dataframe we will work with to plot
var1 = map_data_year$Removals_Total_County_per1K
data <- cbind(mdata,var1)
#data$var1[data$var1==0] <- NA
# --------------------------------
# Compute scale
# --------------------------------
colours = c("#969696","#eda8a9","#cf3946")
#colours = c("#c6c6c6","#818181","#4d4d4d")
labels <- c()
brks <- c(0,3, 5, 50)
for(idx in 1:length(brks)){
labels <- c(labels,round(brks[idx + 1], 2))
}
labels <- labels[1:length(labels)-1]
# define a new variable on the data set just as above
data$brks <- cut(data$var1,
breaks = brks,
include.lowest = TRUE,
labels = labels)
brks_scale <- levels(data$brks)
labels_scale <- (brks_scale)
# --------------------------------
univar_plot <-plot_usmap(data = data, values = "brks", include = c("TX"), color = "black") +
theme_map() +
scale_fill_manual(
values = colours,
name = legend_text,
drop = FALSE,
labels = labels_scale,
guide = guide_legend(
direction = "horizontal",
keyheight = unit(6, units = "mm"),
keywidth = unit(65 / length(labels), units = "mm"),
title.position = 'top',
title.hjust = 0,
label.hjust = 1,
nrow = 1,
byrow = T,
reverse = F,
label.position = "bottom"),
na.translate = FALSE) +
theme(plot.background = element_rect(color = "white", fill = "white")) +
theme(legend.text=element_text(size=12)) +
theme(legend.background = element_rect(color = "white", fill = "white")) +
theme(legend.position="top") + theme(text=element_text(size=12))
return(univar_plot)
} # END OF FUNCTION # 3 updated
# ---------------------------------
# 2021 Texas Maps with binned data
# ---------------------------------
fig_homes <- create_homes_plot_simple_3brks(map_data, 2021, states) + theme(text=element_text(size=12), legend.text=element_text(size=10))
fig_removals <- create_removals_plot_simple_3brks(map_data, 2021) + theme(text=element_text(size=12), legend.text=element_text(size=10))
grid.arrange(fig_homes+theme(plot.title = element_text(hjust = 0.5)),fig_removals+theme(plot.title = element_text(hjust = 0.5)),
nrow = 1)

# ---------------------------------
# 2021 Bivariate Map
# ---------------------------------
create_homes_removals_plot(map_data, 2021, states)

# -----------------------------------------------------
# Examining WHERE the high-need counties are located
# -----------------------------------------------------
bar <- extract_dataframe(map_data, 2021) %>% filter(CBC== "DFPS")
high_need_df <- filter(bar, fill=="#5a3f49") %>% select("Year", "County",
"DFPS_Region")
table(high_need_df$Region)
< table of extent 0 >
high_need_df <- within(high_need_df,
DFPS_Region<- factor(DFPS_Region,
levels=names(sort(table(DFPS_Region),
decreasing=FALSE))))
ylab_test <-("DFPS\n Region")
ggplot(high_need_df, aes(y = DFPS_Region)) +
geom_bar(fill="#5a3f49") + theme(axis.text.x = element_text(color="black", size=12, angle=0)) + theme(axis.text.y = element_text(color="black", size=12, angle=0)) + labs(y = "DFPS Region", x = "County Count") + theme(text = element_text(size = 14)) +
theme(plot.title = element_text(hjust = 0.5)) +
theme(axis.text.x = element_text(color="black", size=12, angle=0)) +
theme(axis.text.y = element_text(color="black", size=14, angle=0)) +
theme(axis.title = element_text(size = 16)) +
theme(legend.text = element_text(size = 14)) +
theme(legend.title = element_text(size = 14)) +
theme(plot.title = element_text(size = 14)) + ylab(ylab_test) + theme(axis.title.y=element_text(angle=0,vjust=0.5)) + scale_x_continuous(breaks = c(0,5,10,15)) + xlim(0,15.1) + theme(plot.margin = margin(t = 10, # Top margin
r = 50, # Right margin
b = 5, # Bottom margin
l = 10))
Scale for 'x' is already present. Adding another scale for 'x', which will
replace the existing scale.

# ---------------------
# Homes Map - for GIF
# ---------------------
library(ggtext)
my_caption = "<span style='color:#000000'>2011</span> <span style='color:#ececec'>2013 2015 2017 2019 2021</span>"
fig = create_homes_plot_simple(map_data, 2011, states)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

# ---------------------
# Homes Map - for GIF
# ---------------------
library(ggtext)
my_caption = "<span style='color:#ececec'>2011</span> <span style='color:#000000'>2013</span> <span style='color:#ececec'>2015 2017 2019 2021</span>"
fig = create_homes_plot_simple(map_data, 2013, states)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

# ---------------------
# Homes Map - for GIF
# ---------------------
library(ggtext)
my_caption = "<span style='color:#ececec'>2011 2013</span> <span style='color:#000000'>2015</span> <span style='color:#ececec'>2017 2019 2021</span>"
fig = create_homes_plot_simple(map_data, 2015, states)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

# ---------------------
# Homes Map - for GIF
# ---------------------
library(ggtext)
my_caption = "<span style='color:#ececec'>2011 2013 2015</span> <span style='color:#000000'>2017</span> <span style='color:#ececec'>2019 2021</span>"
fig = create_homes_plot_simple(map_data, 2017, states)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

# ---------------------
# Homes Map - for GIF
# ---------------------
library(ggtext)
my_caption = "<span style='color:#ececec'>2011 2013 2015 2017</span> <span style='color:#000000'>2019</span> <span style='color:#ececec'>2021</span>"
fig = create_homes_plot_simple(map_data, 2019, states)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

# ---------------------
# Homes Map - for GIF
# ---------------------
library(ggtext)
my_caption = "<span style='color:#ececec'>2011 2013 2015 2017 2019</span> <span style='color:#000000'>2021</span>"
fig = create_homes_plot_simple(map_data, 2021, states)
fig +
labs(caption=my_caption) +
theme(plot.caption = element_text(hjust=0.15, size=rel(1.22))) +
theme(
plot.caption = element_markdown(lineheight = 1.1, size=20, face="bold"),
text=element_text(size=12)
) + theme(legend.text=element_text(size=10))

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoc2hpbnkpCmxpYnJhcnkoZHBseXIpIApsaWJyYXJ5KHRpZHlyKSAKbGlicmFyeShnZ3Bsb3QyKSAKbGlicmFyeShyZWFkcikKbGlicmFyeShtYXBzKQpsaWJyYXJ5KHVzbWFwKQpsaWJyYXJ5KGdyaWRFeHRyYSkKbGlicmFyeShiaXNjYWxlKQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoc2YpCmxpYnJhcnkoc2hpbnl0aGVtZXMpCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIGltcG9ydCBkYXRhCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCkNoaWxkcmVuX1RYIDwtcmVhZC5jc3YoIkNEYXRhL0NoaWxkcmVuX1RYLmNzdiIpCkhvbWVzIDwtcmVhZC5jc3YoIkNEYXRhL0hvbWVzLmNzdiIpClJlbW92YWxzIDwtcmVhZC5jc3YoIkNEYXRhL1JlbW92YWxzLmNzdiIpCm1hcF9kYXRhIDwtIHJlYWQuY3N2KCJDRGF0YS9TaGlueV9tYXBfZGF0YS5jc3YiKQoKc3RhdGVzIDwtIG1hcF9kYXRhKCJzdGF0ZSIpICU+JSBmaWx0ZXIocmVnaW9uID09ICJ0ZXhhcyIpICU+JSBmaWx0ZXIob3JkZXIgPiAxMzAyNSkgJT4lCiAgdXNtYXBfdHJhbnNmb3JtKCkKd3JpdGVfY3N2KHN0YXRlcywgIlNoaW55QXBwL0NEYXRhL3N0YXRlcy5jc3YiKQoKYGBgCgpgYGB7cn0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIENSRUFUSU5HIEJMQU5LIE1BUCBPRiBUSEUgVEVYQVMgQ09VTlRJRVMKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQptYXBfZGF0YSRlbXB0eV92ZWMgPSByZXAoTkEsIDI1NCkKcGxvdF91c21hcChkYXRhID0gbWFwX2RhdGEsIHZhbHVlcyA9ICJlbXB0eV92ZWMiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siKSArIAogIHRoZW1lX21hcCgpICsKICAgIHNjYWxlX2ZpbGxfbWFudWFsKAogICAgICAgICAgdmFsdWVzID0gIndoaXRlIiwgbmEudmFsdWU9IndoaXRlIikgKwogIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJncmF5IiwgZmlsbCA9ICJncmF5IikpIAoKIyAtLS0tLS0tLS0tLS0tLS0KCmBgYAoKCmBgYHtyfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgQ1JFQVRJTkcgTUFQIE9GIFRIRSBURVhBUyBERlBTIFJFR0lPTlMKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQpsZWdlbmRfdGV4dCA9ICJERlBTIFJlZ2lvbiIKCiAgIyBGaWx0ZXIgZm9yIENob3NlbiBZZWFyCiAgbWFwX2RhdGFfeWVhciA8LSBmaWx0ZXIobWFwX2RhdGEsIFllYXIgPT0gMjAyMSkKICAKICAjIEJ1aWxkaW5nIHRoZSBwYXJ0cyBvZiB0aGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoCiAgbWRhdGEgPC0gbWFwX2RhdGFfeWVhciAlPiUgc2VsZWN0KCJZZWFyIiwgIkNvdW50eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiRFJlZ19OdW0iLCAiZmlwcyIsICJsb24iLCAibGF0IikKICAKICAjIGNyZWF0ZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGggdG8gcGxvdAogIHZhcjEgPSBtYXBfZGF0YV95ZWFyJERSZWdfTnVtCiAgZGF0YSA8LSBjYmluZChtZGF0YSx2YXIxKSAgCiAgCiAgZGF0YSR2YXIxW2RhdGEkdmFyMT09MF0gPC0gTkEgCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICMgQ29tcHV0ZSBzY2FsZQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICBjb2xvdXJzID0gYygiI2Y1ODIzMSIsIiM0MmQ0ZjQiLCIjOTExZWI0IiwiI2ZhYmVkNCIsIiMwMDdjN2MiLCIjYWFmZmMzIiwiIzQzNjNkOCIsIiNkY2JlZmYiLCIjYzUwMjc1IiwiI2ZmZTExOSIsIiM5OEQ2NDAiKQogIAogIGxhYmVscyA8LSBjKCkKICBicmtzIDwtIGMoMCwxLCAyLCAzLCA0LCA1LCA2LCA3LCA4LCA5LDEwLDExKQogIAogIGZvcihpZHggaW4gMTpsZW5ndGgoYnJrcykpewogICAgbGFiZWxzIDwtIGMobGFiZWxzLHJvdW5kKGJya3NbaWR4ICsgMV0sIDIpKQogIH0KICBsYWJlbHMgPC0gbGFiZWxzWzE6bGVuZ3RoKGxhYmVscyktMV0KICAjIGRlZmluZSBhIG5ldyB2YXJpYWJsZSBvbiB0aGUgZGF0YSBzZXQganVzdCBhcyBhYm92ZQogIGRhdGEkYnJrcyA8LSBjdXQoZGF0YSR2YXIxLCAKICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGJya3MsIAogICAgICAgICAgICAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGxhYmVscykKICBicmtzX3NjYWxlIDwtIGxldmVscyhkYXRhJGJya3MpCiAgbGFiZWxzX3NjYWxlIDwtIChicmtzX3NjYWxlKQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAKcGxvdF91c21hcChkYXRhID0gZGF0YSwgdmFsdWVzID0gImJya3MiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgdGhlbWVfbWFwKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIG5hbWUgPSBsZWdlbmRfdGV4dCwKICAgICAgZHJvcCA9IEZBTFNFLCAKICAgICAgbGFiZWxzID0gYygiIDEgICBMdWJib2NrIiwiIDIgICBBYmlsZW5lIiwiIDMgICBBcmxpbmd0b24iLCIgNCAgIFR5bGVyIiwiIDUgICBCZWF1bW9udCIsIiA2ICAgSG91c3RvbiIsIiA3ICAgQXVzdGluIiwiIDggICBTYW4gQW50b25pbyIsIiA5ICAgTWlkbGFuZCIsIjEwICBFbCBQYXNvIiwiMTEgIEVkaW5idXJnIiksCiAgICAgIGd1aWRlID0gZ3VpZGVfbGVnZW5kKAogICAgICAgIGRpcmVjdGlvbiA9ICJ2ZXJ0aWNhbCIsCiAgICAgICAga2V5aGVpZ2h0ID0gdW5pdCg2LCB1bml0cyA9ICJtbSIpLAogICAgICAgIGtleXdpZHRoID0gdW5pdCgxMDAgLyBsZW5ndGgobGFiZWxzKSwgdW5pdHMgPSAibW0iKSwKICAgICAgICB0aXRsZS5wb3NpdGlvbiA9ICd0b3AnLAogICAgICAgIHRpdGxlLmhqdXN0ID0gMCwKICAgICAgICBsYWJlbC5oanVzdCA9IDAsCiAgICAgICAgbnJvdyA9IDEyLAogICAgICAgIGJ5cm93ID0gRiwKICAgICAgICByZXZlcnNlID0gRiwKICAgICAgICBsYWJlbC5wb3NpdGlvbiA9ICJyaWdodCIpLAogICAgICBuYS50cmFuc2xhdGUgPSBGQUxTRSkgKyAKICAgIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAid2hpdGUiKSkgKwogICAgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTQpKSArIAogICAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIndoaXRlIikpICsgCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249ImxlZnQiKQogIAojbGlicmFyeShyYWdnKQojcmFnZzo6YWdnX3BuZygicmFnZ181eDUucG5nIiwgd2lkdGggPSA1LCBoZWlnaHQgPSA1LCB1bml0cyA9ICJpbiIsIHJlcyA9IDMwMCwgc2NhbGluZyA9IDAuNSkKI2ZpZzAxCiNkZXYub2ZmKCkKICAKYGBgCgpgYGB7cn0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIERldGVybWluaW5nIHRoZSBCaW5uZWQgSW50ZXJ2YWxzIGZvciB0aGUgSG9tZXMgYW5kIFJlbW92YWxzIERhdGEKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAptZGF0YSA8LSBtYXBfZGF0YSAlPiUgc2VsZWN0KCJZZWFyIiwgIkNvdW50eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICJIb21lc19Ub3RhbF9Db3VudHlfcGVyMTAwSyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlbW92YWxzX1RvdGFsX0NvdW50eV9wZXIxSyIsICJDQkMiKQoKIyBPbmx5IHdhbnQgdGhlIGRhdGEgcG9pbnRzIGZyb20gY291bnRpZXMgd2l0aCBERlBTIGZvc3RlciBjYXJlIChub3QgQ0JDIGZvc3RlciBjYXJlKQptZGF0YSA8LSBtZGF0YSAlPiUgZmlsdGVyKENCQyA9PSAiREZQUyIpIAoKbWRhdGEkWWVhcjwtYXMuZmFjdG9yKG1kYXRhJFllYXIpCgpuZXcxIDwtbWRhdGEgJT4lIGdyb3VwX2J5KENvdW50eSkgJT4lIHN1bW1hcmlzZShNZWFuSG9tZXMgPSBtZWFuKEhvbWVzX1RvdGFsX0NvdW50eV9wZXIxMDBLKSkgJT4lIHNlbGVjdCgiTWVhbkhvbWVzIikgCgpuZXcyIDwtbWRhdGEgJT4lIGdyb3VwX2J5KENvdW50eSkgJT4lIHN1bW1hcmlzZShNZWFuUmVtb3ZhbHMgPSBtZWFuKFJlbW92YWxzX1RvdGFsX0NvdW50eV9wZXIxSykpICU+JSBzZWxlY3QoIk1lYW5SZW1vdmFscyIpCgpuZXcxJE1lYW5Ib21lc1tuZXcxJE1lYW5Ib21lcz09MF0gPC0gTkEgCm5ldzIkTWVhblJlbW92YWxzW25ldzIkTWVhblJlbW92YWxzPT0wXSA8LSBOQSAKCiMgUGxvdCAxCmxheW91dChtYXQgPSBtYXRyaXgoYygxLDIpLDIsMSwgYnlyb3c9VFJVRSksICBoZWlnaHQgPSBjKDEsOCkpCnBhcihtYXI9YygwLCAzLjEsIDEuMSwgMi4xKSkKYm94cGxvdChuZXcxJE1lYW5Ib21lcywgaG9yaXpvbnRhbD1UUlVFICwgeWxpbT1jKDAsNTApLCB4YXh0PSJuIiAsIGNvbD1yZ2IoMy8yNTUsMTQ5LzI1NSwxMTQvMjU1LDAuODUpICwgZnJhbWU9RikKcGFyKG1hcj1jKDQsIDMuMSwgMS4xLCAyLjEpKQpoaXN0KG5ldzEkTWVhbkhvbWVzLCBicmVha3M9NDAgLCBjb2w9cmdiKDAvMjU1LDAvMjU1LDEyNC8yNTUsMC44NSkgLCBib3JkZXI9VCAsIG1haW49IiIgLCB4bGFiPSJBdmVyYWdlIE51bWJlciBvZiBIb21lcyBQZXIgMTAwSyBSZXNpZGVudHMgYmV0d2VlbiAyMDExLTIwMjEiLCB4bGltPWMoMCw1MCkpCgojIFBsb3QgMgpsYXlvdXQobWF0ID0gbWF0cml4KGMoMSwyKSwyLDEsIGJ5cm93PVRSVUUpLCAgaGVpZ2h0ID0gYygxLDgpKQpwYXIobWFyPWMoMCwgMy4xLCAxLjEsIDIuMSkpCmJveHBsb3QobmV3MiRNZWFuUmVtb3ZhbHMsIGhvcml6b250YWw9VFJVRSAsIHlsaW09YygwLDE1KSwgeGF4dD0ibiIgLCBjb2w9cmdiKDMvMjU1LDE0OS8yNTUsMTE0LzI1NSwwLjg1KSAsIGZyYW1lPUYpICsgZ2VvbV9obGluZSh4aW50ZXJjZXB0PTEwKSAKcGFyKG1hcj1jKDQsIDMuMSwgMS4xLCAyLjEpKQpoaXN0KG5ldzIkTWVhblJlbW92YWxzLCBicmVha3M9NDAgLCBjb2w9cmdiKDAvMjU1LDAvMjU1LDEyNC8yNTUsMC44NSkgLCBib3JkZXI9VCAsIG1haW49IiIgLCB4bGFiPSJBdmVyYWdlIE51bWJlciBvZiBSZW1vdmFscyBQZXIgMUsgQ2hpbGRyZW4gYmV0d2VlbiAyMDExLTIwMjEiLCB4bGltPWMoMCwxNSkpIAoKIyBCaW5zIGZvciBIb21lcyAKcXVhbnRpbGUobmV3MSRNZWFuSG9tZXMscHJvYnMgPSAwLjMzMzMzLG5hLnJtID0gVFJVRSkKcXVhbnRpbGUobmV3MSRNZWFuSG9tZXMscHJvYnMgPSAwLjY2NjY3LG5hLnJtID0gVFJVRSkKCiMgQmlucyBmb3IgUmVtb3ZhbHMKcXVhbnRpbGUobmV3MiRNZWFuUmVtb3ZhbHMscHJvYnMgPSAwLjMzMzMzLG5hLnJtID0gVFJVRSkKcXVhbnRpbGUobmV3MiRNZWFuUmVtb3ZhbHMscHJvYnMgPSAwLjY2NjY3LG5hLnJtID0gVFJVRSkKYGBgCgoKYGBge3J9CiMgdGVzdGluZyBvdXQgdGhlIGV4Y2x1ZGUgaW5wdXQgaW4gcGxvdF91c21hcAojIGFsc28gdGVzdGluZyBhZGRpbmcgdGhlIG91dGxpbmUgb2YgdGhlIFRleGFzIHBhbmhhbmRsZQoKY291bnRpZXMgPC0gbWFwX2RhdGEoImNvdW50eSIpICU+JSBmaWx0ZXIocmVnaW9uID09ICJ0ZXhhcyIpICU+JSBmaWx0ZXIoc3VicmVnaW9uPT1jKCJ0cmF2aXMiKSkgJT4lCiAgdXNtYXBfdHJhbnNmb3JtKCkKCm1hcF9kYXRhX3llYXIgPC0gZmlsdGVyKG1hcF9kYXRhLCBZZWFyID09IDIwMjEpCmZpcHNfbGlzdCA9IChtYXBfZGF0YV95ZWFyJGZpcHNbbWFwX2RhdGFfeWVhciRDQkM9PSJDQkMiXSkKCnAgPC0gcGxvdF91c21hcChkYXRhID0gbWFwX2RhdGFfeWVhciwgdmFsdWVzID0gImVtcHR5X3ZlYyIsIGluY2x1ZGUgPSBjKCJUWCIpLCBleGNsdWRlID0gZmlwc19saXN0LCBjb2xvciA9ICJibGFjayIpCgpwbG90X3VzbWFwKGRhdGEgPSBtYXBfZGF0YV95ZWFyLCB2YWx1ZXMgPSAiZW1wdHlfdmVjIiwgaW5jbHVkZSA9IGMoIlRYIiksIGV4Y2x1ZGUgPSBmaXBzX2xpc3QsIGNvbG9yID0gImJsYWNrIikgKyAKICB0aGVtZV9tYXAoKSArCiAgICBzY2FsZV9maWxsX21hbnVhbCgKICAgICAgICAgIHZhbHVlcyA9ICJ3aGl0ZSIsIG5hLnZhbHVlPSJ3aGl0ZSIpICsKICB0aGVtZShwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAiZ3JheSIsIGZpbGwgPSAiZ3JheSIpKSArCiAgZ2VvbV9wYXRoKGRhdGEgPSBzdGF0ZXMsIAogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcuMSwKICAgICAgICAgICAgICAgICAgIHkgPSBsYXQuMSksCiAgICAgICAgICAgICAgIGNvbG9yID0gInJlZCIpICsKICBnZW9tX3BhdGgoZGF0YSA9IGNvdW50aWVzLCAKICAgICAgICAgICAgICAgYWVzKHggPSBsb25nLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gbGF0LjEpLAogICAgICAgICAgICAgICBjb2xvciA9ICJibHVlIikgCgoKYGBgCgoKCmBgYHtyfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBQbG90dGluZyBGdW5jdGlvbnMKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpjcmVhdGVfaG9tZXNfcmVtb3ZhbHNfcGxvdCA8LSBmdW5jdGlvbihtYXBfZGF0YSwgeWVhciwgc3RhdGVzKSB7CiAgCiAgY29sb3JfbWFwID0gYygiI2RhNGY1OCIsIiNlZGE4YTkiLCIjZThlN2U2IiwKICAgICAgICAgICAgICAgICIjYTQ0YzU1IiwiI2IwOWNhNSIsIiNhNGQ1ZTEiLAogICAgICAgICAgICAgICAgIiM1YTNmNDkiLCIjNWI3ZDhmIiwiIzQzYWFjMCIpCgogICMgRmlsdGVyIGZvciBDaG9zZW4gWWVhcgogIG1hcF9kYXRhX3llYXIgPC0gZmlsdGVyKG1hcF9kYXRhLCBZZWFyID09IHllYXIpCiAgCiAgZmlwc19saXN0ID0gKG1hcF9kYXRhX3llYXIkZmlwc1ttYXBfZGF0YV95ZWFyJENCQz09IkNCQyJdKQoKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIyBUaGUgYnJlYWtzOgogIHhfYnJrX3BvaW50cyA9IGMoMywgNSkgICAjIHJlbW92YWxzCiAgeV9icmtfcG9pbnRzID0gYyg2LCAxMSkgICMgaG9tZXMKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgCiAgIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAogIG1kYXRhIDwtIG1hcF9kYXRhX3llYXIgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIsICJmaXBzIiwgImxvbiIsICJsYXQiLCJDQkMiKQogIAogICMgY3JlYXRlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aCB0byBwbG90CiAgdmFyMSA9IG1hcF9kYXRhX3llYXIkUmVtb3ZhbHNfVG90YWxfQ291bnR5X3BlcjFLCiAgdmFyMiA9IG1hcF9kYXRhX3llYXIkSG9tZXNfVG90YWxfQ291bnR5X3BlcjEwMEsKICBkYXRhIDwtIGNiaW5kKG1kYXRhLHZhcjEsdmFyMikgIAogIAogIHggPSBhcy5udW1lcmljKHVubGlzdChkYXRhWzhdKSkKICB5ID0gYXMubnVtZXJpYyh1bmxpc3QoZGF0YVs5XSkpCiAgCiAgIyBjcmVhdGUgMyBidWNrZXRzIGZvciB2YXJpYWJsZSAxCiAgcXVhbnRpbGVzX3ggPC0gcXVhbnRpbGUoeCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBjKDAsZWNkZih4KSh4X2Jya19wb2ludHNbMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2RmKHgpKHhfYnJrX3BvaW50c1syXSksMSksIG5hLnJtID0gVFJVRSkKICAjIGNyZWF0ZSAzIGJ1Y2tldHMgZm9yIHZhcmlhYmxlIDIKICBxdWFudGlsZXNfeSA8LSBxdWFudGlsZSh5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9icyA9IGMoMCxlY2RmKHkpKHlfYnJrX3BvaW50c1sxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjZGYoeSkoeV9icmtfcG9pbnRzWzJdKSwxKSwgbmEucm0gPSBUUlVFKQogIAogICMgY3JlYXRlIGNvbG9yIHNjYWxlIHRoYXQgZW5jb2RlcyB0d28gdmFyaWFibGVzCiAgYml2YXJpYXRlX2NvbG9yX3NjYWxlIDwtIHRpYmJsZSgKICAgICIzIC0gMyIgPSBjb2xvcl9tYXBbMV0sICMgaGlnaCBYLCBoaWdoIFkKICAgICIyIC0gMyIgPSBjb2xvcl9tYXBbMl0sCiAgICAiMSAtIDMiID0gY29sb3JfbWFwWzNdLCAjIGxvdyBYLCBoaWdoIFkKICAgICIzIC0gMiIgPSBjb2xvcl9tYXBbNF0sCiAgICAiMiAtIDIiID0gY29sb3JfbWFwWzVdLCAjIG1lZGl1bSBYLCBtZWRpdW0gWQogICAgIjEgLSAyIiA9IGNvbG9yX21hcFs2XSwKICAgICIzIC0gMSIgPSBjb2xvcl9tYXBbN10sICMgaGlnaCBYLCBsb3cgWQogICAgIjIgLSAxIiA9IGNvbG9yX21hcFs4XSwKICAgICIxIC0gMSIgPSBjb2xvcl9tYXBbOV0gIyBsb3cgWCwgbG93IFkKICApICU+JQogICAgZ2F0aGVyKCJncm91cCIsICJmaWxsIikKICAKICAjIGN1dCBpbnRvIGdyb3VwcyBkZWZpbmVkIGFib3ZlIGFuZCBqb2luIGZpbGwKICBiYXIgPC0gZGF0YSAlPiUKICAgIG11dGF0ZSgKICAgICAgeF9xdWFudGlsZXMgPSBjdXQoCiAgICAgICAgeCwKICAgICAgICBicmVha3MgPSBxdWFudGlsZXNfeCwKICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUKICAgICAgKSwKICAgICAgeV9xdWFudGlsZXMgPSBjdXQoCiAgICAgICAgeSwKICAgICAgICBicmVha3MgPSBxdWFudGlsZXNfeSwKICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUKICAgICAgKSwKICAgICAgZ3JvdXAgPSBwYXN0ZSgKICAgICAgICBhcy5udW1lcmljKHhfcXVhbnRpbGVzKSwgIi0iLAogICAgICAgIGFzLm51bWVyaWMoeV9xdWFudGlsZXMpCiAgICAgICkKICAgICkgJT4lCiAgICAjIHdlIG5vdyBqb2luIHRoZSBhY3R1YWwgaGV4IHZhbHVlcyBwZXIgImdyb3VwIgogICAgIyBzbyBlYWNoIGNvdW50eSBoYXMgYSBoZXggdmFsdWUgYmFzZWQgb24geCBhbmQgeQogICAgbGVmdF9qb2luKGJpdmFyaWF0ZV9jb2xvcl9zY2FsZSwgYnkgPSAiZ3JvdXAiKQogIAogIGZvbyA9IGJhciAlPiUgc2VsZWN0KGZpcHMsZmlsbCkKICBjb2xvdXJzID0gY29sb3JfbWFwCiAgCiAgIyMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIGJpdmFyX3Bsb3QgPC0gcGxvdF91c21hcChkYXRhID0gZm9vLCB2YWx1ZXMgPSAiZmlsbCIsIGluY2x1ZGUgPSBjKCJUWCIpLCBleGNsdWRlID0gZmlwc19saXN0LCBjb2xvciA9ICJibGFjayIsICkgKyAgCiAgICBzY2FsZV9maWxsX21hbnVhbCgKICAgICAgdmFsdWVzID0gY29sb3VycywKICAgICAgYnJlYWtzID0gY29sb3VycywKICAgICAgZHJvcCA9IEZBTFNFLCBuYS52YWx1ZSA9ICJ3aGl0ZSIpICsgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSArCiAgICB0aGVtZShwbG90LmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIndoaXRlIikpICArCiAgZ2VvbV9wYXRoKGRhdGEgPSBzdGF0ZXMsIAogICAgICAgICAgICAgICBhZXMoeCA9IGxvbmcuMSwKICAgICAgICAgICAgICAgICAgIHkgPSBsYXQuMSksCiAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIikgCiAgCiAgcmV0dXJuKGJpdmFyX3Bsb3QpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyAxCgpjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUgPC0gZnVuY3Rpb24obWFwX2RhdGEsIHllYXIsIHN0YXRlcykgewogIAogIGxlZ2VuZF90ZXh0ID0gIkZBRCBIb21lcyBwZXIgMTAwSyByZXNpZGVudHMiCiAgCiAgIyBGaWx0ZXIgZm9yIENob3NlbiBZZWFyCiAgbWFwX2RhdGFfeWVhciA8LSBmaWx0ZXIobWFwX2RhdGEsIFllYXIgPT0geWVhcikKICAKICBmaXBzX2xpc3QgPSAobWFwX2RhdGFfeWVhciRmaXBzW21hcF9kYXRhX3llYXIkQ0JDPT0iQ0JDIl0pCiAgCiAgIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAogIG1kYXRhIDwtIG1hcF9kYXRhX3llYXIgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIsICJmaXBzIiwgImxvbiIsICJsYXQiLCAiQ0JDIikKICAKICAjIGNyZWF0ZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGggdG8gcGxvdAogIHZhcjEgPSBtYXBfZGF0YV95ZWFyJEhvbWVzX1RvdGFsX0NvdW50eV9wZXIxMDBLCiAgZGF0YSA8LSBjYmluZChtZGF0YSx2YXIxKSAgCiAgCiAgZGF0YSR2YXIxW2RhdGEkdmFyMT09MF0gPC0gTkEgCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICMgQ29tcHV0ZSBzY2FsZQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAjY29sb3VycyA9IGMoIiNhOWE5YTkiLCIjZjU1NzAyIiwiI2YwN2QwMyIsIiMyNTk5OWIiLCIjMDA3YzdmIiwiIzAxNWM1ZCIpCiAgY29sb3VycyA9IGMoIiNhOWE5YTkiLCIjM2YyZTg0IiwiIzEwMzJhMSIsIiMyNTk5OWIiLCIjMDA3YzdmIiwiIzAxNWM1ZCIpCiAgbGFiZWxzIDwtIGMoKQogIGJya3MgPC0gYygwLDEwLCAyNSwgNTAsIDc1LCAxMDAsIDEyNSkKICBmb3IoaWR4IGluIDE6bGVuZ3RoKGJya3MpKXsKICAgIGxhYmVscyA8LSBjKGxhYmVscyxyb3VuZChicmtzW2lkeCArIDFdLCAyKSkKICB9CiAgbGFiZWxzIDwtIGxhYmVsc1sxOmxlbmd0aChsYWJlbHMpLTFdCiAgIyBkZWZpbmUgYSBuZXcgdmFyaWFibGUgb24gdGhlIGRhdGEgc2V0IGp1c3QgYXMgYWJvdmUKICBkYXRhJGJya3MgPC0gY3V0KGRhdGEkdmFyMSwgCiAgICAgICAgICAgICAgICAgICBicmVha3MgPSBicmtzLCAKICAgICAgICAgICAgICAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsYWJlbHMpCiAgYnJrc19zY2FsZSA8LSBsZXZlbHMoZGF0YSRicmtzKQogIGxhYmVsc19zY2FsZSA8LSAoYnJrc19zY2FsZSkKICAKICBsYWJlbHNfc2NhbGUgPSBhcHBlbmQobGFiZWxzX3NjYWxlLCAiWkVSTyIpCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogIHVuaXZhcl9wbG90IDwtcGxvdF91c21hcChkYXRhID0gZGF0YSwgdmFsdWVzID0gImJya3MiLCBpbmNsdWRlID0gYygiVFgiKSwgZXhjbHVkZSA9IGZpcHNfbGlzdCwgY29sb3IgPSAiYmxhY2siKSArIAogICAgdGhlbWVfbWFwKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIG5hbWUgPSBsZWdlbmRfdGV4dCwKICAgICAgZHJvcCA9IEZBTFNFLCAKICAgICAgbGFiZWxzID0gbGFiZWxzX3NjYWxlLAogICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAga2V5aGVpZ2h0ID0gdW5pdCg2LCB1bml0cyA9ICJtbSIpLAogICAgICAgIGtleXdpZHRoID0gdW5pdCgxMDAgLyBsZW5ndGgobGFiZWxzKSwgdW5pdHMgPSAibW0iKSwKICAgICAgICB0aXRsZS5wb3NpdGlvbiA9ICd0b3AnLAogICAgICAgIHRpdGxlLmhqdXN0ID0gMCwKICAgICAgICBsYWJlbC5oanVzdCA9IDEsCiAgICAgICAgbnJvdyA9IDEsCiAgICAgICAgYnlyb3cgPSBULAogICAgICAgIHJldmVyc2UgPSBGLAogICAgICAgIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpLCAKICAgICAgICBuYS50cmFuc2xhdGUgPSBUUlVFLCAgbmEudmFsdWUgPSAieWVsbG93IikgKyAKICAgIHRoZW1lKHBsb3QuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAid2hpdGUiKSkgKwogICAgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTQpKSArIAogICAgdGhlbWUobGVnZW5kLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoY29sb3IgPSAid2hpdGUiLCBmaWxsID0gIndoaXRlIikpICsgCiAgICB0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIpICArCiAgICBnZW9tX3BhdGgoZGF0YSA9IHN0YXRlcywgCiAgICAgICAgICAgICAgIGFlcyh4ID0gbG9uZy4xLAogICAgICAgICAgICAgICAgICAgeSA9IGxhdC4xKSwKICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSAKICAKICByZXR1cm4odW5pdmFyX3Bsb3QpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyAyCgpjcmVhdGVfcmVtb3ZhbHNfcGxvdF9zaW1wbGUgPC0gZnVuY3Rpb24obWFwX2RhdGEsIHllYXIpIHsKICAKICBsZWdlbmRfdGV4dCA9ICJSZW1vdmFscyBwZXIgMUsgY2hpbGRyZW4iCiAgCiAgIyBGaWx0ZXIgZm9yIENob3NlbiBZZWFyCiAgbWFwX2RhdGFfeWVhciA8LSBmaWx0ZXIobWFwX2RhdGEsIFllYXIgPT0geWVhcikKICAKICAjIEJ1aWxkaW5nIHRoZSBwYXJ0cyBvZiB0aGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoCiAgbWRhdGEgPC0gbWFwX2RhdGFfeWVhciAlPiUgc2VsZWN0KCJZZWFyIiwgIkNvdW50eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiUmVnaW9uIiwgImZpcHMiLCAibG9uIiwgImxhdCIpCiAgCiAgIyBjcmVhdGUgZGF0YWZyYW1lIHdlIHdpbGwgd29yayB3aXRoIHRvIHBsb3QKICB2YXIxID0gbWFwX2RhdGFfeWVhciRSZW1vdmFsc19Ub3RhbF9Db3VudHlfcGVyMUsKICBkYXRhIDwtIGNiaW5kKG1kYXRhLHZhcjEpICAKICAKICBkYXRhJHZhcjFbZGF0YSR2YXIxPT0wXSA8LSBOQSAKICAKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIyBDb21wdXRlIHNjYWxlCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICNjb2xvdXJzID0gYygiI2E5YTlhOSIsIiMxMDMyYTEiLCIjM2YyZTg0IiwiIzZlMmE2NyIsIiM5YzI0NDkiLCIjY2MyMDJhIikKICBjb2xvdXJzID0gYygiI2E5YTlhOSIsIiNmMDdkMDMiLCIjZjU1NzAyIiwiI2NjMjAyYSIsIiM5YzI0NDkiLCAiIzZlMmE2NyIpCiAgbGFiZWxzIDwtIGMoKQogIGJya3MgPC0gYygwLDUsIDEwLCAxNSwgMjAsIDMwLCA1MCkKICBmb3IoaWR4IGluIDE6bGVuZ3RoKGJya3MpKXsKICAgIGxhYmVscyA8LSBjKGxhYmVscyxyb3VuZChicmtzW2lkeCArIDFdLCAyKSkKICB9CiAgbGFiZWxzIDwtIGxhYmVsc1sxOmxlbmd0aChsYWJlbHMpLTFdCiAgIyBkZWZpbmUgYSBuZXcgdmFyaWFibGUgb24gdGhlIGRhdGEgc2V0IGp1c3QgYXMgYWJvdmUKICBkYXRhJGJya3MgPC0gY3V0KGRhdGEkdmFyMSwgCiAgICAgICAgICAgICAgICAgICBicmVha3MgPSBicmtzLCAKICAgICAgICAgICAgICAgICAgIGluY2x1ZGUubG93ZXN0ID0gVFJVRSwgCiAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBsYWJlbHMpCiAgYnJrc19zY2FsZSA8LSBsZXZlbHMoZGF0YSRicmtzKQogIGxhYmVsc19zY2FsZSA8LSAoYnJrc19zY2FsZSkKICAKICBsYWJlbHNfc2NhbGUgPSBhcHBlbmQobGFiZWxzX3NjYWxlLCAiWkVSTyIpCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogIHVuaXZhcl9wbG90IDwtcGxvdF91c21hcChkYXRhID0gZGF0YSwgdmFsdWVzID0gImJya3MiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgdGhlbWVfbWFwKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIG5hbWUgPSBsZWdlbmRfdGV4dCwKICAgICAgZHJvcCA9IEZBTFNFLCAKICAgICAgbGFiZWxzID0gbGFiZWxzX3NjYWxlLAogICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAga2V5aGVpZ2h0ID0gdW5pdCg2LCB1bml0cyA9ICJtbSIpLAogICAgICAgIGtleXdpZHRoID0gdW5pdCgxMDAgLyBsZW5ndGgobGFiZWxzKSwgdW5pdHMgPSAibW0iKSwKICAgICAgICB0aXRsZS5wb3NpdGlvbiA9ICd0b3AnLAogICAgICAgIHRpdGxlLmhqdXN0ID0gMCwKICAgICAgICBsYWJlbC5oanVzdCA9IDEsCiAgICAgICAgbnJvdyA9IDEsCiAgICAgICAgYnlyb3cgPSBULAogICAgICAgIHJldmVyc2UgPSBGLAogICAgICAgIGxhYmVsLnBvc2l0aW9uID0gImJvdHRvbSIpLAogICAgICBuYS50cmFuc2xhdGUgPSBUUlVFLCBuYS52YWx1ZSA9ICJ5ZWxsb3ciKSArIAogICAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpKSArCiAgICB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xNCkpICsgCiAgICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAid2hpdGUiKSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikKICAKICByZXR1cm4odW5pdmFyX3Bsb3QpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyAzCgojIGV4dHJhY3QgZGF0YWZyYW1lIGZyb20gYml2YXJpYXRlIG1hcApleHRyYWN0X2RhdGFmcmFtZSA8LSBmdW5jdGlvbihtYXBfZGF0YSwgeWVhcikgewogIAogIGNvbG9yX21hcCA9IGMoIiNkYTRmNTgiLCIjZWRhOGE5IiwiI2U4ZTdlNiIsCiAgICAgICAgICAgICAgICAiI2E0NGM1NSIsIiNiMDljYTUiLCIjYTRkNWUxIiwKICAgICAgICAgICAgICAgICIjNWEzZjQ5IiwiIzViN2Q4ZiIsIiM0M2FhYzAiKQogIAogICMgRmlsdGVyIGZvciBDaG9zZW4gWWVhcgogIG1hcF9kYXRhX3llYXIgPC0gZmlsdGVyKG1hcF9kYXRhLCBZZWFyID09IHllYXIpCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICMgVGhlIGJyZWFrczoKICB4X2Jya19wb2ludHMgPSBjKDMsIDUpICAgIyByZW1vdmFscwogIHlfYnJrX3BvaW50cyA9IGMoNiwgMTEpICAjIGhvbWVzCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogICMgQnVpbGRpbmcgdGhlIHBhcnRzIG9mIHRoZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGgKICBtZGF0YSA8LSBtYXBfZGF0YV95ZWFyICU+JSBzZWxlY3QoIlllYXIiLCAiQ291bnR5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJERlBTX1JlZ2lvbiIsICJmaXBzIiwgImxvbiIsICJsYXQiLCJDQkMiKQogIAogICMgY3JlYXRlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aCB0byBwbG90CiAgdmFyMSA9IG1hcF9kYXRhX3llYXIkUmVtb3ZhbHNfVG90YWxfQ291bnR5X3BlcjFLCiAgdmFyMiA9IG1hcF9kYXRhX3llYXIkSG9tZXNfVG90YWxfQ291bnR5X3BlcjEwMEsKICBkYXRhIDwtIGNiaW5kKG1kYXRhLHZhcjEsdmFyMikgIAogIAogIHggPSBhcy5udW1lcmljKHVubGlzdChkYXRhWzhdKSkKICB5ID0gYXMubnVtZXJpYyh1bmxpc3QoZGF0YVs5XSkpCiAgCiAgIyBjcmVhdGUgMyBidWNrZXRzIGZvciB2YXJpYWJsZSAxCiAgcXVhbnRpbGVzX3ggPC0gcXVhbnRpbGUoeCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvYnMgPSBjKDAsZWNkZih4KSh4X2Jya19wb2ludHNbMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlY2RmKHgpKHhfYnJrX3BvaW50c1syXSksMSksIG5hLnJtID0gVFJVRSkKICAjIGNyZWF0ZSAzIGJ1Y2tldHMgZm9yIHZhcmlhYmxlIDIKICBxdWFudGlsZXNfeSA8LSBxdWFudGlsZSh5LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBwcm9icyA9IGMoMCxlY2RmKHkpKHlfYnJrX3BvaW50c1sxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVjZGYoeSkoeV9icmtfcG9pbnRzWzJdKSwxKSwgbmEucm0gPSBUUlVFKQogIAogICMgY3JlYXRlIGNvbG9yIHNjYWxlIHRoYXQgZW5jb2RlcyB0d28gdmFyaWFibGVzCiAgYml2YXJpYXRlX2NvbG9yX3NjYWxlIDwtIHRpYmJsZSgKICAgICIzIC0gMyIgPSBjb2xvcl9tYXBbMV0sICMgaGlnaCBYLCBoaWdoIFkKICAgICIyIC0gMyIgPSBjb2xvcl9tYXBbMl0sCiAgICAiMSAtIDMiID0gY29sb3JfbWFwWzNdLCAjIGxvdyBYLCBoaWdoIFkKICAgICIzIC0gMiIgPSBjb2xvcl9tYXBbNF0sCiAgICAiMiAtIDIiID0gY29sb3JfbWFwWzVdLCAjIG1lZGl1bSBYLCBtZWRpdW0gWQogICAgIjEgLSAyIiA9IGNvbG9yX21hcFs2XSwKICAgICIzIC0gMSIgPSBjb2xvcl9tYXBbN10sICMgaGlnaCBYLCBsb3cgWQogICAgIjIgLSAxIiA9IGNvbG9yX21hcFs4XSwKICAgICIxIC0gMSIgPSBjb2xvcl9tYXBbOV0gIyBsb3cgWCwgbG93IFkKICApICU+JQogICAgZ2F0aGVyKCJncm91cCIsICJmaWxsIikKICAKICAjIGN1dCBpbnRvIGdyb3VwcyBkZWZpbmVkIGFib3ZlIGFuZCBqb2luIGZpbGwKICBiYXIgPC0gZGF0YSAlPiUKICAgIG11dGF0ZSgKICAgICAgeF9xdWFudGlsZXMgPSBjdXQoCiAgICAgICAgeCwKICAgICAgICBicmVha3MgPSBxdWFudGlsZXNfeCwKICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUKICAgICAgKSwKICAgICAgeV9xdWFudGlsZXMgPSBjdXQoCiAgICAgICAgeSwKICAgICAgICBicmVha3MgPSBxdWFudGlsZXNfeSwKICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUKICAgICAgKSwKICAgICAgZ3JvdXAgPSBwYXN0ZSgKICAgICAgICBhcy5udW1lcmljKHhfcXVhbnRpbGVzKSwgIi0iLAogICAgICAgIGFzLm51bWVyaWMoeV9xdWFudGlsZXMpCiAgICAgICkKICAgICkgJT4lCiAgICAjIHdlIG5vdyBqb2luIHRoZSBhY3R1YWwgaGV4IHZhbHVlcyBwZXIgImdyb3VwIgogICAgIyBzbyBlYWNoIGNvdW50eSBoYXMgYSBoZXggdmFsdWUgYmFzZWQgb24geCBhbmQgeQogICAgbGVmdF9qb2luKGJpdmFyaWF0ZV9jb2xvcl9zY2FsZSwgYnkgPSAiZ3JvdXAiKQogIAogIGZvbyA9IGJhciAlPiUgc2VsZWN0KGZpcHMsZmlsbCkKICBjb2xvdXJzID0gY29sb3JfbWFwCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIHJldHVybihiYXIpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyA0CgojIGV4dHJhY3QgZGF0YWZyYW1lIGZyb20gdW5pdmFyaWF0ZSByZW1vdmFscyBtYXAKZXh0cmFjdF9kYXRhZnJhbWUyIDwtIGZ1bmN0aW9uKG1hcF9kYXRhLCB5ZWFyKSB7CiAgCiAgbGVnZW5kX3RleHQgPSAiUmVtb3ZhbHMgcGVyIDFLIGNoaWxkcmVuIgogIAogICMgRmlsdGVyIGZvciBDaG9zZW4gWWVhcgogIG1hcF9kYXRhX3llYXIgPC0gZmlsdGVyKG1hcF9kYXRhLCBZZWFyID09IHllYXIpCiAgCiAgIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAogIG1kYXRhIDwtIG1hcF9kYXRhX3llYXIgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIsICJmaXBzIiwgImxvbiIsICJsYXQiKQogIAogICMgY3JlYXRlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aCB0byBwbG90CiAgdmFyMSA9IG1hcF9kYXRhX3llYXIkUmVtb3ZhbHNfVG90YWxfQ291bnR5X3BlcjFLCiAgZGF0YSA8LSBjYmluZChtZGF0YSx2YXIxKSAgCiAgCiAgZGF0YSR2YXIxW2RhdGEkdmFyMT09MF0gPC0gTkEgCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICMgQ29tcHV0ZSBzY2FsZQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICBjb2xvdXJzID0gYygiI2E5YTlhOSIsIiNlYWMyNTkiLCIjZjM5ZjYyIiwiI2Y2NzMwMCIsIiNlNTI4MzUiLCIjODEwMzAxIikKICBsYWJlbHMgPC0gYygpCiAgYnJrcyA8LSBjKDAsNSwgMTAsIDE1LCAyMCwgMzAsIDUwKQogIGZvcihpZHggaW4gMTpsZW5ndGgoYnJrcykpewogICAgbGFiZWxzIDwtIGMobGFiZWxzLHJvdW5kKGJya3NbaWR4ICsgMV0sIDIpKQogIH0KICBsYWJlbHMgPC0gbGFiZWxzWzE6bGVuZ3RoKGxhYmVscyktMV0KICAjIGRlZmluZSBhIG5ldyB2YXJpYWJsZSBvbiB0aGUgZGF0YSBzZXQganVzdCBhcyBhYm92ZQogIGRhdGEkYnJrcyA8LSBjdXQoZGF0YSR2YXIxLCAKICAgICAgICAgICAgICAgICAgIGJyZWFrcyA9IGJya3MsIAogICAgICAgICAgICAgICAgICAgaW5jbHVkZS5sb3dlc3QgPSBUUlVFLCAKICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IGxhYmVscykKICBicmtzX3NjYWxlIDwtIGxldmVscyhkYXRhJGJya3MpCiAgbGFiZWxzX3NjYWxlIDwtIChicmtzX3NjYWxlKQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICAKICByZXR1cm4oZGF0YSkKfSAjIEVORCBPRiBGVU5DVElPTiAjIDUKCmBgYAoKCmBgYHtyfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgSG9tZXMgYmV0d2VlbiAyMDExLTIwMTgKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKSG9tZXMgJT4lIGZpbHRlcihZZWFyICVpbiUgYygyMDExLCAyMDEyLCAyMDEzLCAyMDE0LCAyMDE1LCAyMDE2LCAyMDE3LCAyMDE4KSkgJT4lIGdyb3VwX2J5KFllYXIpICU+JSBzdW1tYXJpc2UoVG90YWwgPSBzdW0oQ291bnQpKQoKSG9tZXMgJT4lIGZpbHRlcihZZWFyICVpbiUgYygyMDExLCAyMDEyLCAyMDEzLCAyMDE0LCAyMDE1LCAyMDE2KSkgJT4lIGdyb3VwX2J5KFllYXIsIFR5cGUpICU+JSBzdW1tYXJpc2UoVG90YWwgPSBzdW0oQ291bnQpKSAlPiUgCiAgICAgICAgICAgIGdncGxvdChhZXMoeCA9ICBZZWFyLCB5ID0gVG90YWwsIGZpbGwgPSBUeXBlKSkgKyAKICAgICAgICAgICAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgICAgICAgICAgIGdndGl0bGUoIiIpICsKICAgICAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKG5hbWU9IlllYXIiLCBsaW1pdHM9YygyMDEwLjUsIDIwMTYuNSksIGJyZWFrcyA9IGMoMjAxMSwyMDEyLDIwMTMsMjAxNCwyMDE1LDIwMTYpKSArIAogICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogICAgICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyAKICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT0xNCwgYW5nbGU9MCkpICsgCiAgICAgICAgICAgIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkgKwogICAgICAgICAgICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSAgKwogICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICsgCiAgICAgICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiSG9tZSBUeXBlIiwgdmFsdWVzID0gYygiIzYzNjM2MyIsIiNhZWFlYWUiLCJibGFjayIpKSAKCmBgYAoKCmBgYHtyIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSAyfQpIb21lc19SZWdpb24gPC0gSG9tZXMgJT4lIGZpbHRlcihDQkMgPT0gIkRGUFMiKSAlPiUgZ3JvdXBfYnkoUmVnaW9uLCBZZWFyKSAlPiUgc3VtbWFyaXNlKFRvdGFsX0hvbWVzID0gc3VtKENvdW50KSkKClBvcHVsYXRpb25fUmVnaW9uIDwtIENoaWxkcmVuX1RYICU+JSBncm91cF9ieShSZWdpb24sIFllYXIpICU+JSBzdW1tYXJpc2UoVG90YWxfUG9wID0gc3VtKFRvdGFsX1BvcHVsYXRpb24pKQoKSG9tZXNfdG9wbG90IDwtIEhvbWVzX1JlZ2lvbiAlPiUgbWVyZ2UoUG9wdWxhdGlvbl9SZWdpb24sYnk9YygiUmVnaW9uIiwiWWVhciIpKSAKSG9tZXNfdG9wbG90JEhvbWVzUGVyMTAwSyA9IChIb21lc190b3Bsb3QkVG90YWxfSG9tZXMvSG9tZXNfdG9wbG90JFRvdGFsX1BvcCkqMTAwMDAwCiAgCmNvbG91cnMgPSBjKCIjNDJkNGY0IiwiI2M1MDI3NSIpCgojeWxhYl9yb3QgPC0gZ3N1YigiICIsICJcbiIsICJGQUQgSG9tZXMgUGVyIDEwMEsgUmVzaWRlbnRzIikKeWxhYl90ZXN0IDwtKCJGQUQgSG9tZXNcbnBlciAxMDBLXG5yZXNpZGVudHMiKQoKSG9tZXNfdG9wbG90ICU+JSAgZmlsdGVyKFJlZ2lvbiAlaW4lIGMoIjItQWJpbGVuZSIsIjktTWlkbGFuZCIpKSAlPiUKICBnZ3Bsb3QoIGFlcyh4PVllYXIsIHk9SG9tZXNQZXIxMDBLLCBncm91cD1SZWdpb24sIGNvbG9yID0gUmVnaW9uKSkrCiAgICBnZW9tX2xpbmUoc2l6ZT0zLjUsIGFscGhhPTAuOCkgKwogICAgc2NhbGVfY29sb3VyX21hbnVhbChuYW1lPSJERlBTIFJlZ2lvbiIsCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsbGFiZWxzID0gYygiIDItQWJpbGVuZSIsIiA5LU1pZGxhbmQiKSkgKyAKICAgICAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IGMoMjAxMSwyMDEzLDIwMTUsMjAxNywyMDE5LDIwMjEpKSArIHlsYWIoeWxhYl90ZXN0KSArIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoYW5nbGU9MCx2anVzdD0wLjUpKSArIAogICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogICAgICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyAKICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT0xNCwgYW5nbGU9MCkpICsgCiAgICAgICAgICAgIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkgKwogICAgICAgICAgICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSAgKwogICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpCmBgYCAKCgpgYGB7ciBmaWcud2lkdGggPSA0LCBmaWcuaGVpZ2h0ID0gMn0KCkhvbWVzX1llYXIgPC0gSG9tZXMgJT4lIGZpbHRlcihDQkMgPT0gIkRGUFMiKSAlPiUgZ3JvdXBfYnkoWWVhciwgVHlwZSkgJT4lIHN1bW1hcmlzZShUb3RhbF9Ib21lcyA9IHN1bShDb3VudCkpCiAgClBvcHVsYXRpb25fWWVhciA8LSBtYXBfZGF0YSAlPiUgZmlsdGVyKENCQyA9PSAiREZQUyIpICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKFRvdGFsX1BvcCA9IHN1bShUb3RhbF9Qb3B1bGF0aW9uKSkKCkhvbWVzX1BvcHVsYXRpb25fWWVhciA8LSBIb21lc19ZZWFyICU+JSBtZXJnZShQb3B1bGF0aW9uX1llYXIsYnk9YygiWWVhciIpKSAKSG9tZXNfUG9wdWxhdGlvbl9ZZWFyJEhvbWVzUGVyMTAwSyA9IChIb21lc19Qb3B1bGF0aW9uX1llYXIkVG90YWxfSG9tZXMvSG9tZXNfUG9wdWxhdGlvbl9ZZWFyJFRvdGFsX1BvcCkqMTAwMDAwCgp5bGFiX3Rlc3QgPC0oIkZBRCBIb21lc1xucGVyIDEwMEtcbnJlc2lkZW50cyIpCgpIb21lc19Qb3B1bGF0aW9uX1llYXIgJT4lIGZpbHRlcihZZWFyICVpbiUgYygyMDExLDIwMTMsMjAxNSwyMDE3LDIwMTksMjAyMSkpICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKFRvdGFsID0gc3VtKEhvbWVzUGVyMTAwSykpCgpIb21lc19Qb3B1bGF0aW9uX1llYXIgJT4lIGZpbHRlcihZZWFyICVpbiUgYygyMDExLDIwMTMsMjAxNSwyMDE3LDIwMTksMjAyMSkpICU+JSBnZ3Bsb3QoYWVzKHggPSAgWWVhciwgeSA9IEhvbWVzUGVyMTAwSywgZmlsbD1UeXBlKSkgKyAKICAgICAgICAgICAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgICAgICAgICAgIGdndGl0bGUoIiIpICsgCiAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArCiAgICAgICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9MTIsIGFuZ2xlPTApKSArIAogICAgICAgICAgICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyAKICAgICAgICAgICAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSArCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICsKICAgICAgICAgICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICArCiAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgKwogICAgICAgICAgICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygyMDExLDIwMTMsMjAxNSwyMDE3LDIwMTksMjAyMSkpICsgeWxhYih5bGFiX3Rlc3QpICsgdGhlbWUoYXhpcy50aXRsZS55PWVsZW1lbnRfdGV4dChhbmdsZT0wLHZqdXN0PTAuNTUsaGp1c3Q9MC41MCkpICsgCiAgICAgICAgICAgIHNjYWxlX2ZpbGxfbWFudWFsKG5hbWUgPSAiSG9tZSBUeXBlIiwgdmFsdWVzID0gYygiIzYzNjM2MyIsIiNhZWFlYWUiLCJibGFjayIpKQoKYGBgCgoKCmBgYHtyfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgSG9tZXMgVGV4YXMgTWFwcwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgojIC0tLS0tLS0tLS0tLS0tLS0tCiMgMjAxMSBiYXIgY2hhcnQKIyAtLS0tLS0tLS0tLS0tLS0tLQptYXBfZGF0YV8yMDExIDwtIG1hcF9kYXRhICU+JSBmaWx0ZXIoKFllYXIgPT0gIjIwMTEiKSAmIChDQkMgPT0gIkRGUFMiKSkgJT4lICBmaWx0ZXIoSG9tZXNfVG90YWxfQ291bnR5PT0wKSAKCnN1bShtYXBfZGF0YV8yMDExJEhvbWVzX1RvdGFsX0NvdW50eT09MCkKCm1hcF9kYXRhXzIwMTEgPC0gd2l0aGluKG1hcF9kYXRhXzIwMTEsIAogICAgICAgICAgICAgICAgICAgUmVnaW9uPC0gZmFjdG9yKFJlZ2lvbiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV2ZWxzPW5hbWVzKHNvcnQodGFibGUoUmVnaW9uKSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVjcmVhc2luZz1GQUxTRSkpKSkKZ2dwbG90KG1hcF9kYXRhXzIwMTEsIGFlcyh5ID0gUmVnaW9uKSkgKwogIGdlb21fYmFyKGZpbGw9ImJsYWNrIikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTksIGFuZ2xlPTApKSArIGxhYnMoeSA9ICJSZWdpb24iLCB4ID0gIkNvdW50eSBDb3VudCIpCgojIC0tLS0tLS0tLS0tLS0tLS0tCiMgMjAxNSBiYXIgY2hhcnQKIyAtLS0tLS0tLS0tLS0tLS0tLQptYXBfZGF0YV8yMDE1IDwtIG1hcF9kYXRhJT4lIGZpbHRlcigoWWVhciA9PSAiMjAxNSIpICYgKENCQyA9PSAiREZQUyIpKSAgJT4lIGZpbHRlcihIb21lc19Ub3RhbF9Db3VudHk9PTApIAoKc3VtKG1hcF9kYXRhXzIwMTUkSG9tZXNfVG90YWxfQ291bnR5PT0wKQoKbWFwX2RhdGFfMjAxNSA8LSB3aXRoaW4obWFwX2RhdGFfMjAxNSwgCiAgICAgICAgICAgICAgICAgICBSZWdpb248LSBmYWN0b3IoUmVnaW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9bmFtZXMoc29ydCh0YWJsZShSZWdpb24pLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWNyZWFzaW5nPUZBTFNFKSkpKQpnZ3Bsb3QobWFwX2RhdGFfMjAxNSwgYWVzKHkgPSBSZWdpb24pKSArCiAgZ2VvbV9iYXIoZmlsbD0iYmxhY2siKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9OSwgYW5nbGU9MCkpICsgbGFicyh5ID0gIkRSZWdfTnVtIiwgeCA9ICJDb3VudHkgQ291bnQiKQoKIyAtLS0tLS0tLS0tLS0tLS0tLQojIG1hcHMgZmlndXJlICgyIFllYXJzKQojIC0tLS0tLS0tLS0tLS0tLS0tCmZpZzEgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTEsIHN0YXRlcykgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKQpmaWcyID0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDEyLCBzdGF0ZXMpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgCmZpZzMgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTMsIHN0YXRlcykgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSAKZmlnNCA9IGNyZWF0ZV9ob21lc19wbG90X3NpbXBsZShtYXBfZGF0YSwgMjAxNCwgc3RhdGVzKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpIApmaWc1ID0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDE1LCBzdGF0ZXMpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgCmZpZzYgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTYsIHN0YXRlcykgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSAKZmlnNyA9IGNyZWF0ZV9ob21lc19wbG90X3NpbXBsZShtYXBfZGF0YSwgMjAxNywgc3RhdGVzKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpIApmaWc4ID0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDE4LCBzdGF0ZXMpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikgCmZpZzkgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTksIHN0YXRlcykgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSAKZmlnMTAgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMjAsIHN0YXRlcykgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSAKZmlnMTEgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMjEsIHN0YXRlcykgKyAKICB0aGVtZShsZWdlbmQucG9zaXRpb249Im5vbmUiKSAKCmdyaWQuYXJyYW5nZShmaWcxK2dndGl0bGUoIjIwMTEiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC4zNSkpLCAKICAgICAgICAgICAgIGZpZzExK2dndGl0bGUoIjIwMjEiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC4zNSkpLCAKICAgICAgICAgICAgIG5yb3cgPSAxKQoKIyAtLS0tLS0tLS0tLS0tLS0tLQojIG1hcHMgZmlndXJlcyAoMiBZZWFycyAtIGFub3RoZXIgdmVyc2lvbikKIyAtLS0tLS0tLS0tLS0tLS0tLQpsaWJyYXJ5KGdncHVicikKZmlnMCA9IGNyZWF0ZV9ob21lc19wbG90X3NpbXBsZShtYXBfZGF0YSwgMjAyMSwgc3RhdGVzKSAKZmlnMCA8LSBmaWcwICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSkgCgpsZWcgPC0gZ2V0X2xlZ2VuZChmaWcwKQpsZWdoIDwtIGFzX2dncGxvdChsZWcpICMgY29udmVydGluZyB0byBnZ3Bsb3QKbGVnaCAKCmhvbWVzXzIwMTEgPC0gZmlnMStnZ3RpdGxlKCIyMDExIikrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuMzUpKQpob21lc18yMDIxIDwtIGZpZzExK2dndGl0bGUoIjIwMjEiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC4zNSkpIAogCmxpYnJhcnkocGF0Y2h3b3JrKQpsYXlvdXQgPC0gIgpBIwpCQwpCQwoiCmxlZ2ggKyBob21lc18yMDExICsgaG9tZXNfMjAyMSArIHBsb3RfbGF5b3V0KGRlc2lnbiA9IGxheW91dCkgCgpgYGAKCmBgYHtyfQpmaWcxdCA8LSBmaWcxK2dndGl0bGUoIjIwMTEiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC4zNSkpCmZpZzJ0IDwtIGZpZzIrZ2d0aXRsZSgiMjAxMiIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjM1KSkKZmlnM3QgPC0gZmlnMytnZ3RpdGxlKCIyMDEzIikrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuMzUpKQpmaWc0dCA8LSBmaWc0K2dndGl0bGUoIjIwMTQiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC4zNSkpCmZpZzV0IDwtIGZpZzUrZ2d0aXRsZSgiMjAxNSIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjM1KSkKZmlnNnQgPC0gZmlnNitnZ3RpdGxlKCIyMDE2IikrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuMzUpKQpmaWc3dCA8LSBmaWc3K2dndGl0bGUoIjIwMTciKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC4zNSkpCmZpZzh0IDwtIGZpZzgrZ2d0aXRsZSgiMjAxOCIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjM1KSkKZmlnOXQgPC0gZmlnOStnZ3RpdGxlKCIyMDE5IikrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuMzUpKQpmaWcxMHQgPC0gZmlnMTArZ2d0aXRsZSgiMjAyMCIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjM1KSkKZmlnMTF0IDwtIGZpZzExK2dndGl0bGUoIjIwMjEiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC4zNSkpCgojbGlicmFyeShwYXRjaHdvcmspCiNsYXlvdXQgPC0gIgojQUJDCiMiCiNmaWcxdCArIGZpZzN0ICsgZmlnNXQgKyBwbG90X2xheW91dChkZXNpZ24gPSBsYXlvdXQpIAojZmlnN3QgKyBmaWc5dCArIGZpZzExdCArIHBsb3RfbGF5b3V0KGRlc2lnbiA9IGxheW91dCkgCgpncmlkLmFycmFuZ2UoZmlnMXQsZmlnM3QsZmlnNXQsIAogICAgICAgICAgICAgbnJvdyA9IDEpCgpncmlkLmFycmFuZ2UoZmlnN3QsIGZpZzl0LCBmaWcxMXQsIAogICAgICAgICAgICAgbnJvdyA9IDEpCmBgYAoKCgpgYGB7cn0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFJlbW92YWxzIGJldHdlZW4gMjAxMS0yMDE4CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KClJlbW92YWxzICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKFRvdGFsID0gc3VtKFJlbW92YWxzKSkgCgpSZW1vdmFscyAlPiUgZmlsdGVyKFllYXIgJWluJSBjKDIwMTEsIDIwMTIsIDIwMTMsIDIwMTQsIDIwMTUsIDIwMTYsIDIwMTcsIDIwMTgsIDIwMTksIDIwMjAsIDIwMjEpKSAlPiUgZ3JvdXBfYnkoWWVhciwgUmVtb3ZhbC5TdGFnZSkgJT4lIHN1bW1hcmlzZShUb3RhbCA9IHN1bShSZW1vdmFscykpICU+JSBnZ3Bsb3QoYWVzKHggPSAgWWVhciwgeSA9IFRvdGFsLCBmaWxsID0gUmVtb3ZhbC5TdGFnZSkpICsgCiAgICAgICAgICAgIGdlb21fYmFyKHN0YXQgPSAnaWRlbnRpdHknKSArIAogICAgICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0zMCkpICsgCiAgICAgICAgICAgIHRoZW1lKGF4aXMudGV4dC55ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9MTIsIGFuZ2xlPTApKSArIAogICAgICAgICAgICB0aGVtZShheGlzLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNikpICsKICAgICAgICAgICAgdGhlbWUobGVnZW5kLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgKwogICAgICAgICAgICB0aGVtZShsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgICsKICAgICAgICAgICAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArCiAgICAgICAgICAgIGdndGl0bGUoIiIpICsKICAgICAgICAgICAgc2NhbGVfeF9jb250aW51b3VzKG5hbWU9IlllYXIiLCBsaW1pdHM9YygyMDEwLjUsIDIwMjEuNSksIGJyZWFrcyA9IGMoMjAxMSwyMDEyLDIwMTMsMjAxNCwyMDE1LDIwMTYsMjAxNywyMDE4LDIwMTksMjAyMCwyMDIxKSkgKwogICAgICAgICAgICBzY2FsZV9maWxsX21hbnVhbChuYW1lID0gIlJlbW92YWwgU3RhZ2UiLCB2YWx1ZXMgPSBjKCIjMDU4YWJkIiwiIzFjMzE1MiIpKQoKYGBgCgoKYGBge3IgZmlnLndpZHRoID0gNCwgZmlnLmhlaWdodCA9IDJ9ClJlbW92YWxzX1llYXIgPC0gUmVtb3ZhbHMgJT4lIGdyb3VwX2J5KFllYXIsIFJlbW92YWwuU3RhZ2UpICU+JSBzdW1tYXJpc2UoVG90YWxfUmVtb3ZhbHMgPSBzdW0oUmVtb3ZhbHMpKQoKQ2hpbGRfUG9wdWxhdGlvbl9ZZWFyIDwtIG1hcF9kYXRhICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKENoaWxkX1BvcCA9IHN1bShDaGlsZF9Qb3B1bGF0aW9uKSkKClJlbW92YWxzX1BvcHVsYXRpb25fWWVhciA8LSBSZW1vdmFsc19ZZWFyICU+JSBtZXJnZShDaGlsZF9Qb3B1bGF0aW9uX1llYXIsYnk9YygiWWVhciIpKSAKUmVtb3ZhbHNfUG9wdWxhdGlvbl9ZZWFyJFJlbW92YWxzUGVyMUsgPSAoUmVtb3ZhbHNfUG9wdWxhdGlvbl9ZZWFyJFRvdGFsX1JlbW92YWxzL0NoaWxkX1BvcHVsYXRpb25fWWVhciRDaGlsZF9Qb3ApKjEwMDAKCnlsYWJfdGVzdCA8LSgiUmVtb3ZhbHNcbiBwZXIgMUsgXG5jaGlsZHJlbiIpCgpSZW1vdmFsc19Qb3B1bGF0aW9uX1llYXIgJT4lIGZpbHRlcihZZWFyICVpbiUgYygyMDExLDIwMTMsMjAxNSwyMDE3LDIwMTksMjAyMSkpICU+JSBncm91cF9ieShZZWFyKSAlPiUgc3VtbWFyaXNlKFRvdGFsID0gc3VtKFJlbW92YWxzUGVyMUspKSAlPiUgc3VtbWFyaXNlKE1lYW4gPSBtZWFuKFRvdGFsKSkKClJlbW92YWxzX1BvcHVsYXRpb25fWWVhciAlPiUgZmlsdGVyKFllYXIgJWluJSBjKDIwMTEsMjAxMywyMDE1LDIwMTcsMjAxOSwyMDIxKSkgJT4lIGdncGxvdChhZXMoeCA9ICBZZWFyLCB5ID0gUmVtb3ZhbHNQZXIxSywgZmlsbD1SZW1vdmFsLlN0YWdlKSkgKyAKICAgICAgICAgICAgZ2VvbV9iYXIoc3RhdCA9ICdpZGVudGl0eScpICsgCiAgICAgICAgICAgIGdndGl0bGUoIiIpICsgCiAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSArCiAgICAgICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9MTIsIGFuZ2xlPTApKSArIAogICAgICAgICAgICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTE0LCBhbmdsZT0wKSkgKyAKICAgICAgICAgICAgdGhlbWUoYXhpcy50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTYpKSArCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICsKICAgICAgICAgICAgdGhlbWUobGVnZW5kLnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICArCiAgICAgICAgICAgIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0KSkgKwogICAgICAgICAgICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDIwMTEsMjAxMywyMDE1LDIwMTcsMjAxOSwyMDIxKSkgKyB5bGFiKHlsYWJfdGVzdCkgKyB0aGVtZShheGlzLnRpdGxlLnk9ZWxlbWVudF90ZXh0KGFuZ2xlPTAsdmp1c3Q9MC41MCkpICsgeWxpbSgwLDMuMDEpICsKICAgICAgICAgICAgc2NhbGVfZmlsbF9tYW51YWwobmFtZSA9ICJSZW1vdmFsIFN0YWdlIiwgdmFsdWVzID0gYygiIzU1NTY1QiIsImJsYWNrIikpCmBgYAoKCgpgYGB7cn0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIFJlbW92YWxzIFRleGFzIE1hcHMKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyAtLS0tLS0tLS0tLS0tLS0tLQojIDIwMTggYmFyIGNoYXJ0CiMgLS0tLS0tLS0tLS0tLS0tLS0KcmVtb3ZhbHNfZGF0YV8yMDIxIDwtIGV4dHJhY3RfZGF0YWZyYW1lMihtYXBfZGF0YSwgMjAyMSkKCnJlbW92YWxzX2RhdGFfMjAyMV9oaWdoIDwtIGZpbHRlcihyZW1vdmFsc19kYXRhXzIwMjEgLCBicmtzIT0iNSIpICU+JSBzZWxlY3QoIlllYXIiLCAiQ291bnR5IiwgIlJlZ2lvbiIsImJya3MiKQoKcmVtb3ZhbHNfZGF0YV8yMDIxX2hpZ2ggPC0gd2l0aGluKHJlbW92YWxzX2RhdGFfMjAyMV9oaWdoLCAKICAgICAgICAgICAgICAgICAgIFJlZ2lvbjwtIGZhY3RvcihSZWdpb24sIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldmVscz1uYW1lcyhzb3J0KHRhYmxlKFJlZ2lvbiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY3JlYXNpbmc9RkFMU0UpKSkpCmdncGxvdChyZW1vdmFsc19kYXRhXzIwMjFfaGlnaCwgYWVzKHkgPSBSZWdpb24pKSArCiAgZ2VvbV9iYXIoZmlsbD0iYmxhY2siKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGNvbG9yPSJibGFjayIsIHNpemU9OSwgYW5nbGU9MCkpICsgbGFicyh5ID0gIlJlZ2lvbiIsIHggPSAiQ291bnR5IENvdW50IikKCiMgLS0tLS0tLS0tLS0tLS0tLS0KIyBtYXBzIGZpZ3VyZSAoMiBZZWFycykKIyAtLS0tLS0tLS0tLS0tLS0tLQpmaWczID0gY3JlYXRlX3JlbW92YWxzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDExKSArIAogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCmZpZzQgPSBjcmVhdGVfcmVtb3ZhbHNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMjEpICsgCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uPSJub25lIikKCmdyaWQuYXJyYW5nZShmaWczK2dndGl0bGUoIjIwMTEiKSt0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC4zNSkpLCAKICAgICAgICAgICAgIGZpZzQrZ2d0aXRsZSgiMjAyMSIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjM1KSksIAogICAgICAgICAgICAgbnJvdyA9IDEpCgojIC0tLS0tLS0tLS0tLS0tLS0tCiMgbWFwcyBmaWd1cmVzICgyIFllYXJzIC0gYW5vdGhlciB2ZXJzaW9uKQojIC0tLS0tLS0tLS0tLS0tLS0tCmxpYnJhcnkoZ2dwdWJyKQpmaWcgPSBjcmVhdGVfcmVtb3ZhbHNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMjEpIApmaWcgPC0gZmlnICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSkgCgpsZWcgPC0gZ2V0X2xlZ2VuZChmaWcpCmxlZ2ggPC0gYXNfZ2dwbG90KGxlZykgCmxlZ2gKCnJlbW92YWxzXzIwMTEgPC0gZmlnMytnZ3RpdGxlKCIyMDExIikrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNDEpKQpyZW1vdmFsc18yMDIxIDwtIGZpZzQrZ2d0aXRsZSgiMjAyMSIpK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjQxKSkKIApsaWJyYXJ5KHBhdGNod29yaykKCmxheW91dCA8LSAiCkEjCkJDCkJDCiIKbGVnaCArIHJlbW92YWxzXzIwMTEgKyByZW1vdmFsc18yMDIxICsgcGxvdF9sYXlvdXQoZGVzaWduID0gbGF5b3V0KQpgYGAKCgoKYGBge3J9CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIE1hcCBGdW5jdGlvbnMgZm9yIFRleGFzIE1hcHMgd2l0aCBiaW5uZWQgaW50ZXJ2YWxzCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKIyBNYXAgRnVuY3Rpb24gd2l0aCAzIEJyZWFrcwpjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGVfM2Jya3MgPC0gZnVuY3Rpb24obWFwX2RhdGEsIHllYXIsIHN0YXRlcykgewogIAogIGxlZ2VuZF90ZXh0ID0gIkZBRCBIb21lcyBwZXIgMTAwSyByZXNpZGVudHMiCiAgCiAgIyBGaWx0ZXIgZm9yIENob3NlbiBZZWFyCiAgbWFwX2RhdGFfeWVhciA8LSBmaWx0ZXIobWFwX2RhdGEsIFllYXIgPT0geWVhcikKICAKICBmaXBzX2xpc3QgPSAobWFwX2RhdGFfeWVhciRmaXBzW21hcF9kYXRhX3llYXIkQ0JDPT0iQ0JDIl0pCiAgCiAgIyBCdWlsZGluZyB0aGUgcGFydHMgb2YgdGhlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aAogIG1kYXRhIDwtIG1hcF9kYXRhX3llYXIgJT4lIHNlbGVjdCgiWWVhciIsICJDb3VudHkiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZ2lvbiIsICJmaXBzIiwgImxvbiIsICJsYXQiKQogIAogICMgY3JlYXRlIGRhdGFmcmFtZSB3ZSB3aWxsIHdvcmsgd2l0aCB0byBwbG90CiAgdmFyMSA9IG1hcF9kYXRhX3llYXIkSG9tZXNfVG90YWxfQ291bnR5X3BlcjEwMEsKICBkYXRhIDwtIGNiaW5kKG1kYXRhLHZhcjEpICAKICAKICAjZGF0YSR2YXIxW2RhdGEkdmFyMT09MF0gPC0gTkEgCiAgCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICMgQ29tcHV0ZSBzY2FsZQogICMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KICBjb2xvdXJzID0gYygiIzQzYWFiZiIsIiNhNGQ1ZTEiLCIjOTY5Njk2IikKICAjY29sb3VycyA9IGMoIiM0ZDRkNGQiLCIjODE4MTgxIiwiI2M2YzZjNiIpCiAgbGFiZWxzIDwtIGMoKQogIGJya3MgPC0gYygwLDYsMTEsNTApCiAgZm9yKGlkeCBpbiAxOmxlbmd0aChicmtzKSl7CiAgICBsYWJlbHMgPC0gYyhsYWJlbHMscm91bmQoYnJrc1tpZHggKyAxXSwgMikpCiAgfQogIGxhYmVscyA8LSBsYWJlbHNbMTpsZW5ndGgobGFiZWxzKS0xXQogICMgZGVmaW5lIGEgbmV3IHZhcmlhYmxlIG9uIHRoZSBkYXRhIHNldCBqdXN0IGFzIGFib3ZlCiAgZGF0YSRicmtzIDwtIGN1dChkYXRhJHZhcjEsIAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYnJrcywgCiAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGFiZWxzKQogIGJya3Nfc2NhbGUgPC0gbGV2ZWxzKGRhdGEkYnJrcykKICBsYWJlbHNfc2NhbGUgPC0gKGJya3Nfc2NhbGUpCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogIHVuaXZhcl9wbG90IDwtcGxvdF91c21hcChkYXRhID0gZGF0YSwgdmFsdWVzID0gImJya3MiLCBpbmNsdWRlID0gYygiVFgiKSwgZXhjbHVkZSA9IGZpcHNfbGlzdCwgY29sb3IgPSAiYmxhY2siKSArIAogICAgdGhlbWVfbWFwKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIG5hbWUgPSBsZWdlbmRfdGV4dCwKICAgICAgZHJvcCA9IEZBTFNFLCAKICAgICAgbGFiZWxzID0gbGFiZWxzX3NjYWxlLAogICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAga2V5aGVpZ2h0ID0gdW5pdCg2LCB1bml0cyA9ICJtbSIpLAogICAgICAgIGtleXdpZHRoID0gdW5pdCg2NSAvIGxlbmd0aChsYWJlbHMpLCB1bml0cyA9ICJtbSIpLAogICAgICAgIHRpdGxlLnBvc2l0aW9uID0gJ3RvcCcsCiAgICAgICAgdGl0bGUuaGp1c3QgPSAwLAogICAgICAgIGxhYmVsLmhqdXN0ID0gMSwKICAgICAgICBucm93ID0gMSwKICAgICAgICBieXJvdyA9IFQsCiAgICAgICAgcmV2ZXJzZSA9IEYsCiAgICAgICAgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIiksIAogICAgICAgIG5hLnRyYW5zbGF0ZSA9IEZBTFNFKSArIAogICAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpKSArCiAgICB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikpICsgCiAgICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAid2hpdGUiKSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikgICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikpICsKICAgIGdlb21fcGF0aChkYXRhID0gc3RhdGVzLCAKICAgICAgICAgICAgICAgYWVzKHggPSBsb25nLjEsCiAgICAgICAgICAgICAgICAgICB5ID0gbGF0LjEpLAogICAgICAgICAgICAgICBjb2xvciA9ICJibGFjayIpIAoKICByZXR1cm4odW5pdmFyX3Bsb3QpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyAyIHVwZGF0ZWQKCmNyZWF0ZV9yZW1vdmFsc19wbG90X3NpbXBsZV8zYnJrcyA8LSBmdW5jdGlvbihtYXBfZGF0YSwgeWVhcikgewogIAogIGxlZ2VuZF90ZXh0ID0gIlJlbW92YWxzIHBlciAxSyBjaGlsZHJlbiIKICAKICAjIEZpbHRlciBmb3IgQ2hvc2VuIFllYXIKICBtYXBfZGF0YV95ZWFyIDwtIGZpbHRlcihtYXBfZGF0YSwgWWVhciA9PSB5ZWFyKQogIAogICMgQnVpbGRpbmcgdGhlIHBhcnRzIG9mIHRoZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGgKICBtZGF0YSA8LSBtYXBfZGF0YV95ZWFyICU+JSBzZWxlY3QoIlllYXIiLCAiQ291bnR5IiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJSZWdpb24iLCAiZmlwcyIsICJsb24iLCAibGF0IikKICAKICAjIGNyZWF0ZSBkYXRhZnJhbWUgd2Ugd2lsbCB3b3JrIHdpdGggdG8gcGxvdAogIHZhcjEgPSBtYXBfZGF0YV95ZWFyJFJlbW92YWxzX1RvdGFsX0NvdW50eV9wZXIxSwogIGRhdGEgPC0gY2JpbmQobWRhdGEsdmFyMSkgIAogIAogICNkYXRhJHZhcjFbZGF0YSR2YXIxPT0wXSA8LSBOQSAKICAKICAjIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiAgIyBDb21wdXRlIHNjYWxlCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIGNvbG91cnMgPSBjKCIjOTY5Njk2IiwiI2VkYThhOSIsIiNjZjM5NDYiKQogICNjb2xvdXJzID0gYygiI2M2YzZjNiIsIiM4MTgxODEiLCIjNGQ0ZDRkIikKICBsYWJlbHMgPC0gYygpCiAgYnJrcyA8LSBjKDAsMywgNSwgNTApCiAgZm9yKGlkeCBpbiAxOmxlbmd0aChicmtzKSl7CiAgICBsYWJlbHMgPC0gYyhsYWJlbHMscm91bmQoYnJrc1tpZHggKyAxXSwgMikpCiAgfQogIGxhYmVscyA8LSBsYWJlbHNbMTpsZW5ndGgobGFiZWxzKS0xXQogICMgZGVmaW5lIGEgbmV3IHZhcmlhYmxlIG9uIHRoZSBkYXRhIHNldCBqdXN0IGFzIGFib3ZlCiAgZGF0YSRicmtzIDwtIGN1dChkYXRhJHZhcjEsIAogICAgICAgICAgICAgICAgICAgYnJlYWtzID0gYnJrcywgCiAgICAgICAgICAgICAgICAgICBpbmNsdWRlLmxvd2VzdCA9IFRSVUUsIAogICAgICAgICAgICAgICAgICAgbGFiZWxzID0gbGFiZWxzKQogIGJya3Nfc2NhbGUgPC0gbGV2ZWxzKGRhdGEkYnJrcykKICBsYWJlbHNfc2NhbGUgPC0gKGJya3Nfc2NhbGUpCiAgIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogIAogIHVuaXZhcl9wbG90IDwtcGxvdF91c21hcChkYXRhID0gZGF0YSwgdmFsdWVzID0gImJya3MiLCBpbmNsdWRlID0gYygiVFgiKSwgY29sb3IgPSAiYmxhY2siKSArIAogICAgdGhlbWVfbWFwKCkgKwogICAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICAgIHZhbHVlcyA9IGNvbG91cnMsCiAgICAgIG5hbWUgPSBsZWdlbmRfdGV4dCwKICAgICAgZHJvcCA9IEZBTFNFLCAKICAgICAgbGFiZWxzID0gbGFiZWxzX3NjYWxlLAogICAgICBndWlkZSA9IGd1aWRlX2xlZ2VuZCgKICAgICAgICBkaXJlY3Rpb24gPSAiaG9yaXpvbnRhbCIsCiAgICAgICAga2V5aGVpZ2h0ID0gdW5pdCg2LCB1bml0cyA9ICJtbSIpLAogICAgICAgIGtleXdpZHRoID0gdW5pdCg2NSAvIGxlbmd0aChsYWJlbHMpLCB1bml0cyA9ICJtbSIpLAogICAgICAgIHRpdGxlLnBvc2l0aW9uID0gJ3RvcCcsCiAgICAgICAgdGl0bGUuaGp1c3QgPSAwLAogICAgICAgIGxhYmVsLmhqdXN0ID0gMSwKICAgICAgICBucm93ID0gMSwKICAgICAgICBieXJvdyA9IFQsCiAgICAgICAgcmV2ZXJzZSA9IEYsCiAgICAgICAgbGFiZWwucG9zaXRpb24gPSAiYm90dG9tIiksCiAgICAgIG5hLnRyYW5zbGF0ZSA9IEZBTFNFKSArIAogICAgdGhlbWUocGxvdC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KGNvbG9yID0gIndoaXRlIiwgZmlsbCA9ICJ3aGl0ZSIpKSArCiAgICB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikpICsgCiAgICB0aGVtZShsZWdlbmQuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdChjb2xvciA9ICJ3aGl0ZSIsIGZpbGwgPSAid2hpdGUiKSkgKyAKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbj0idG9wIikgKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSkKICAKICByZXR1cm4odW5pdmFyX3Bsb3QpCn0gIyBFTkQgT0YgRlVOQ1RJT04gIyAzIHVwZGF0ZWQKYGBgCgoKYGBge3J9CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgMjAyMSBUZXhhcyBNYXBzIHdpdGggYmlubmVkIGRhdGEKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmZpZ19ob21lcyA8LSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGVfM2Jya3MobWFwX2RhdGEsIDIwMjEsIHN0YXRlcykgKyB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApKSAKCmZpZ19yZW1vdmFscyA8LSBjcmVhdGVfcmVtb3ZhbHNfcGxvdF9zaW1wbGVfM2Jya3MobWFwX2RhdGEsIDIwMjEpICsgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksIGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSkgCgpncmlkLmFycmFuZ2UoZmlnX2hvbWVzK3RoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpKSxmaWdfcmVtb3ZhbHMrdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSkpLCAKICAgICAgICAgICAgIG5yb3cgPSAxKSAKYGBgCgoKCmBgYHtyIGZpZy53aWR0aCA9IDQsIGZpZy5oZWlnaHQgPSAyfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIDIwMjEgQml2YXJpYXRlIE1hcAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKY3JlYXRlX2hvbWVzX3JlbW92YWxzX3Bsb3QobWFwX2RhdGEsIDIwMjEsIHN0YXRlcykgCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgRXhhbWluaW5nIFdIRVJFIHRoZSBoaWdoLW5lZWQgY291bnRpZXMgYXJlIGxvY2F0ZWQKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKYmFyIDwtIGV4dHJhY3RfZGF0YWZyYW1lKG1hcF9kYXRhLCAyMDIxKSAlPiUgIGZpbHRlcihDQkM9PSAiREZQUyIpCgpoaWdoX25lZWRfZGYgPC0gZmlsdGVyKGJhciwgZmlsbD09IiM1YTNmNDkiKSAlPiUgc2VsZWN0KCJZZWFyIiwgIkNvdW50eSIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiREZQU19SZWdpb24iKQoKdGFibGUoaGlnaF9uZWVkX2RmJFJlZ2lvbikKCmhpZ2hfbmVlZF9kZiA8LSB3aXRoaW4oaGlnaF9uZWVkX2RmLCAKICAgICAgICAgICAgICAgICAgIERGUFNfUmVnaW9uPC0gZmFjdG9yKERGUFNfUmVnaW9uLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXZlbHM9bmFtZXMoc29ydCh0YWJsZShERlBTX1JlZ2lvbiksIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRlY3JlYXNpbmc9RkFMU0UpKSkpCgp5bGFiX3Rlc3QgPC0oIkRGUFNcbiBSZWdpb24iKQoKZ2dwbG90KGhpZ2hfbmVlZF9kZiwgYWVzKHkgPSBERlBTX1JlZ2lvbikpICsKICBnZW9tX2JhcihmaWxsPSIjNWEzZjQ5IikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyBsYWJzKHkgPSAiREZQUyBSZWdpb24iLCB4ID0gIkNvdW50eSBDb3VudCIpICsgdGhlbWUodGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArIAogICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSkgKwogICAgICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChjb2xvcj0iYmxhY2siLCBzaXplPTEyLCBhbmdsZT0wKSkgKyAKICAgICAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoY29sb3I9ImJsYWNrIiwgc2l6ZT0xNCwgYW5nbGU9MCkpICsgCiAgICAgICAgICAgIHRoZW1lKGF4aXMudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE2KSkgKwogICAgICAgICAgICB0aGVtZShsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArCiAgICAgICAgICAgIHRoZW1lKGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSAgKwogICAgICAgICAgICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCkpICsgeWxhYih5bGFiX3Rlc3QpICArIHRoZW1lKGF4aXMudGl0bGUueT1lbGVtZW50X3RleHQoYW5nbGU9MCx2anVzdD0wLjUpKSArIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBjKDAsNSwxMCwxNSkpICsgeGxpbSgwLDE1LjEpICsgdGhlbWUocGxvdC5tYXJnaW4gPSBtYXJnaW4odCA9IDEwLCAgIyBUb3AgbWFyZ2luCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgciA9IDUwLCAgIyBSaWdodCBtYXJnaW4KICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiID0gNSwgICMgQm90dG9tIG1hcmdpbgogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGwgPSAxMCkpCgoKYGBgCgpgYGB7cn0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBIb21lcyBNYXAgLSBmb3IgR0lGIAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKbGlicmFyeShnZ3RleHQpIAoKbXlfY2FwdGlvbiA9ICI8c3BhbiBzdHlsZT0nY29sb3I6IzAwMDAwMCc+MjAxMTwvc3Bhbj4gIDxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDEzICAyMDE1ICAyMDE3ICAyMDE5ICAyMDIxPC9zcGFuPiIKCmZpZyA9IGNyZWF0ZV9ob21lc19wbG90X3NpbXBsZShtYXBfZGF0YSwgMjAxMSwgc3RhdGVzKSAKZmlnICsgCiAgbGFicyhjYXB0aW9uPW15X2NhcHRpb24pICsgCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuMTUsIHNpemU9cmVsKDEuMjIpKSkgKwogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF9tYXJrZG93bihsaW5laGVpZ2h0ID0gMS4xLCBzaXplPTIwLCBmYWNlPSJib2xkIiksIAogICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikKICApICsgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApKSAKCmBgYApgYGB7cn0KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0KIyBIb21lcyBNYXAgLSBmb3IgR0lGIAojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKbGlicmFyeShnZ3RleHQpIAoKbXlfY2FwdGlvbiA9ICI8c3BhbiBzdHlsZT0nY29sb3I6I2VjZWNlYyc+MjAxMTwvc3Bhbj4gIDxzcGFuIHN0eWxlPSdjb2xvcjojMDAwMDAwJz4yMDEzPC9zcGFuPiAgPHNwYW4gc3R5bGU9J2NvbG9yOiNlY2VjZWMnPjIwMTUgIDIwMTcgIDIwMTkgIDIwMjE8L3NwYW4+IgoKZmlnID0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDEzLCBzdGF0ZXMpIApmaWcgKyAKICBsYWJzKGNhcHRpb249bXlfY2FwdGlvbikgKyAKICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3Q9MC4xNSwgc2l6ZT1yZWwoMS4yMikpKSArCiAgdGhlbWUoCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X21hcmtkb3duKGxpbmVoZWlnaHQgPSAxLjEsIHNpemU9MjAsIGZhY2U9ImJvbGQiKSwgCiAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKQogICkgKyB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpIApgYGAKCmBgYHtyfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEhvbWVzIE1hcCAtIGZvciBHSUYgCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpsaWJyYXJ5KGdndGV4dCkgCgpteV9jYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDExICAyMDEzPC9zcGFuPiAgPHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDAnPjIwMTU8L3NwYW4+ICA8c3BhbiBzdHlsZT0nY29sb3I6I2VjZWNlYyc+MjAxNyAgMjAxOSAgMjAyMTwvc3Bhbj4iCgpmaWcgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTUsIHN0YXRlcykgCmZpZyArIAogIGxhYnMoY2FwdGlvbj1teV9jYXB0aW9uKSArIAogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChoanVzdD0wLjE1LCBzaXplPXJlbCgxLjIyKSkpICsKICB0aGVtZSgKICAgIHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfbWFya2Rvd24obGluZWhlaWdodCA9IDEuMSwgc2l6ZT0yMCwgZmFjZT0iYm9sZCIpLCAKICAgIHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpCiAgKSArIHRoZW1lKGxlZ2VuZC50ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEwKSkgCmBgYAoKYGBge3J9CiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgSG9tZXMgTWFwIC0gZm9yIEdJRiAKIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmxpYnJhcnkoZ2d0ZXh0KSAKCm15X2NhcHRpb24gPSAiPHNwYW4gc3R5bGU9J2NvbG9yOiNlY2VjZWMnPjIwMTEgIDIwMTMgIDIwMTU8L3NwYW4+ICA8c3BhbiBzdHlsZT0nY29sb3I6IzAwMDAwMCc+MjAxNzwvc3Bhbj4gIDxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDE5ICAyMDIxPC9zcGFuPiIKCmZpZyA9IGNyZWF0ZV9ob21lc19wbG90X3NpbXBsZShtYXBfZGF0YSwgMjAxNywgc3RhdGVzKSAKZmlnICsgCiAgbGFicyhjYXB0aW9uPW15X2NhcHRpb24pICsgCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuMTUsIHNpemU9cmVsKDEuMjIpKSkgKwogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF9tYXJrZG93bihsaW5laGVpZ2h0ID0gMS4xLCBzaXplPTIwLCBmYWNlPSJib2xkIiksIAogICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikKICApICsgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApKQpgYGAKCmBgYHtyfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEhvbWVzIE1hcCAtIGZvciBHSUYgCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpsaWJyYXJ5KGdndGV4dCkgCgpteV9jYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDExICAyMDEzICAyMDE1ICAyMDE3PC9zcGFuPiAgPHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDAnPjIwMTk8L3NwYW4+ICA8c3BhbiBzdHlsZT0nY29sb3I6I2VjZWNlYyc+MjAyMTwvc3Bhbj4iCgpmaWcgPSBjcmVhdGVfaG9tZXNfcGxvdF9zaW1wbGUobWFwX2RhdGEsIDIwMTksIHN0YXRlcykKZmlnICsgCiAgbGFicyhjYXB0aW9uPW15X2NhcHRpb24pICsgCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KGhqdXN0PTAuMTUsIHNpemU9cmVsKDEuMjIpKSkgKwogIHRoZW1lKAogICAgcGxvdC5jYXB0aW9uID0gZWxlbWVudF9tYXJrZG93bihsaW5laGVpZ2h0ID0gMS4xLCBzaXplPTIwLCBmYWNlPSJib2xkIiksIAogICAgdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMikKICApICsgdGhlbWUobGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTApKQpgYGAKCmBgYHtyfQojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIEhvbWVzIE1hcCAtIGZvciBHSUYgCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpsaWJyYXJ5KGdndGV4dCkgCgpteV9jYXB0aW9uID0gIjxzcGFuIHN0eWxlPSdjb2xvcjojZWNlY2VjJz4yMDExICAyMDEzICAyMDE1ICAyMDE3ICAyMDE5PC9zcGFuPiAgPHNwYW4gc3R5bGU9J2NvbG9yOiMwMDAwMDAnPjIwMjE8L3NwYW4+IgoKZmlnID0gY3JlYXRlX2hvbWVzX3Bsb3Rfc2ltcGxlKG1hcF9kYXRhLCAyMDIxLCBzdGF0ZXMpIApmaWcgKyAKICBsYWJzKGNhcHRpb249bXlfY2FwdGlvbikgKyAKICB0aGVtZShwbG90LmNhcHRpb24gPSBlbGVtZW50X3RleHQoaGp1c3Q9MC4xNSwgc2l6ZT1yZWwoMS4yMikpKSArCiAgdGhlbWUoCiAgICBwbG90LmNhcHRpb24gPSBlbGVtZW50X21hcmtkb3duKGxpbmVoZWlnaHQgPSAxLjEsIHNpemU9MjAsIGZhY2U9ImJvbGQiKSwgCiAgICB0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKQogICkgKyB0aGVtZShsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMCkpIApgYGAKCgoK